Connected IBOutlets are not initialized

2019-05-06 15:45发布

问题:

I've implemented custom UICollectionViewCell class in Swift, created storyboard with UICollectionViewCotroller, assigned my custom controller class, custom cell class, cell id etc... Basically everything required to make UICollectionViewController work.

In storyboard cell prototype I've added few views and connected them as IBOutlets to my custom cell class:

here my IBOutlets in code (as you can see, they are connected):

I registered custom cell class in my controller too:

self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

When I dequeue my cell in code it returns cell of my custom type but both IBOutlets aren't initialised (equal nil)

    let cell = collectionView?.dequeueReusableCellWithReuseIdentifier(reuseIdentifier,
    forIndexPath: indexPath) as MyCollectionViewCell

    if let path = indexPath {
        // Crash here as imageView is nil
        cell.imageView.image = imagesArray[path.item] 
    }

Crashlog:

fatal error: unexpectedly found nil while unwrapping an Optional value

if I put breakpoint on if statement above and do po cell I have this output:

(lldb) po cell
0x00007fa799f4cdf0
 {
  UIKit.UICollectionViewCell = {
    UIKit.UICollectionReusableView = {
      UIKit.UIView = {
        UIKit.UIResponder = {
          ObjectiveC.NSObject = {}
        }
      }
    }
  }
  selectionView = nil
  imageView = nil
}

Any ideas why IBOutlets aren't initialised?

回答1:

I was having the same problem starting in Beta5, though with xib not with storyboard. In the xib case, it appears to be a problem with

init(nibName: nil, bundle: nil) 

not picking up the default xib filename. When I changed to an explicit nibName

init(nibName: "MyClass", bundle: nil) 

then it started working again. Could the the same issue with storyboard - if there's a way to force the storyboard name, I'd try that.



回答2:

It happens because IBOutlets are connected later, after initWithCoder has finished.

To setup your controls after they've been connected, you can override - applyLayoutAttributes: in your UIColletionViewCell subclass.

override func applyLayoutAttributes(layoutAttributes: UICollectionViewLayoutAttributes) {
    setupControls()
}

According to documentation, it's an empty method, meant to be overridden in order to apply custom layout attributes to the view. Sounds about right.



回答3:

Well , I also faced this problem , and my issues is solved by commenting Register api of collection view as following code snippet . I believed that as we are using storyboard . and there we have given all information like (Class , outlets and identifier ) . so storyboard handle all this .

func configureCollectionView(isNib:Bool = false)
{
    if isNib
    {
        //collectionView.register(UINib(nibName: "GalleryCell", bundle:nil), forCellWithReuseIdentifier: identifier)
    }
    else
    {
        //collectionView.register(PhotoCell.self,forCellWithReuseIdentifier:identifier);
    }

}


回答4:

If this is beta 4 or 5, and I think it is based on the IBOutlets being optional, do you have initWithCoder overridden in the class? Even one that does nothing but call super? That being missing might be your problem.

Edit: Have you tried making sure the reuseIdentifiers all match up in the storyboards and code?