Connected IBOutlets are not initialized
Asked Answered
N

4

4

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:

enter image description here

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

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?

Notornis answered 6/8, 2014 at 0:0 Comment(0)
S
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.

Snare answered 24/6, 2015 at 4:57 Comment(0)
P
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.

Photophobia answered 6/8, 2014 at 5:17 Comment(0)
E
1

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);
    }

}
Ectoderm answered 16/12, 2016 at 9:4 Comment(0)
H
0

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?

Hypoxia answered 6/8, 2014 at 1:27 Comment(2)
It is Beta5. In Beta5 IBOutlets are initialised (automatically on Ctrl-drag) as IBOutlet weak var variableName: VarType. Yes, I overrode initWithCoder. It is compile time error in Beta5 - you can't build your app if UIView subclass doesn't override it.Notornis
That's right. It doesn't just crash anymore, it's a real error.Hypoxia

© 2022 - 2024 — McMap. All rights reserved.