6

I'm working with an UICollectionView. As dequeueReusableCell(withReuseIdentifier:for:) expects You must register a class or nib file using the register(_:forCellWithReuseIdentifier:) method before calling this method, I added a line in my viewDidLoad func as

self.collectionView!.register(PhotoCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

Now when I'm using the cell for dequeuing and configuring, I'm getting error and app crashes.

fatal error: unexpectedly found nil while unwrapping an Optional value

This is my DataSource method:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
                                                  for: indexPath) as! PhotoCollectionViewCell

    let aPhoto = photoForIndexPath(indexPath: indexPath)
    cell.backgroundColor = UIColor.white

    cell.imageView.image = aPhoto.thumbnail //this is the line causing error

    return cell
}

And this is my PhotoCollectionViewCell class

class PhotoCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var imageView: UIImageView! //I double checked this IBOutlet whether it connects with Storyboard or not
}


Original question

Now comes the interesting part.

I'm using a prototype cell in the UICollectionView and I set a reusable identifier from attributes inspector. Also I changed the custom class from identity inspector to my PhotoCollectionViewCell.

I searched for the same issue and found out that when using prototype cell, deleting

self.collectionView!.register(PhotoCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) 

from code will work. I gave it a try and it works.

But I'm curious to know the reason behind this issue. I couldn't reproduce the same issue with UITableView but with UICollectionView.

Not a possible duplicate:

This UICollectionView's cell registerClass in Swift is about how to register class in UICollectionView. But my question doesn't expect how to register. My question is about an issue that isn't true with UITableView class but with UICollectionView only. I'm expecting the actual difference between this conflicting issue.

Community
  • 1
  • 1
nayem
  • 7,285
  • 1
  • 33
  • 51
  • Have you added cell identifier in cell in storyboard?? – Abhishek Thapliyal May 22 '17 at 06:08
  • @AbhishekThapliyal, yes! I also mentioned this. – nayem May 22 '17 at 06:10
  • did you use separate xib and custom class ? – KKRocks May 22 '17 at 06:15
  • The prototype cell is connected automatically. If tou register class for the same identifier, you overwrite that connection but no views will be loaded therefore outlets will stay nil. You cannot connect storyboard cells programatically. – Sulthan May 22 '17 at 06:18
  • @KKRocks I used `prototype cell` but with custom class. – nayem May 22 '17 at 06:19
  • in storyboard ? – KKRocks May 22 '17 at 06:19
  • @KKRocks yes! In storyboard. – nayem May 22 '17 at 06:20
  • then you dont need to register cell in viewDidLoad...Remove that line form viewDidLoad. – KKRocks May 22 '17 at 06:21
  • @nayem Add this func code -> `photoForIndexPath(indexPath: indexPath)`. Put breakpoint and check `aPhoto`. – dahiya_boy May 22 '17 at 06:23
  • Possible duplicate of [UICollectionView's cell registerClass in Swift](http://stackoverflow.com/questions/24110811/uicollectionviews-cell-registerclass-in-swift) – Nishant Bhindi May 22 '17 at 06:25
  • @dahiya_boy, I tested that out. `aPhoto` is containing expected value. The problem is in `cell.imageView` as this remains ___nil___. – nayem May 22 '17 at 06:27
  • @nayem Check Cell object. – dahiya_boy May 22 '17 at 06:28
  • @nayem check either you give the identifier to the custom cell from the storyboard/XIB or not? – dahiya_boy May 22 '17 at 06:29
  • @dahiya_boy I did give the `reusable identifier` for the cell in ___attributes inspector___ – nayem May 22 '17 at 06:32
  • @Sulthan it seems my issue is conflicting with [this issue](http://stackoverflow.com/a/43400993/3687801) – nayem May 22 '17 at 06:33
  • I dont see a conflict. – Sulthan May 22 '17 at 06:52
  • Yes! He was using a `prototype` cell giving it an _identifier_ and assigning a _custom class_. But yet the answer suggested to use `tableView.register(MyTableViewCell.self, forCellReuseIdentifier: "Cell")`. And I was also doing the same but with `UICollectionView`. So why shouldn't I need to register cell's class? @Sulthan – nayem May 22 '17 at 07:00
  • You write: *"cell.imageView.image = aPhoto.thumbnail //this is the line causing error"* .. so, which part is causing the error? the `cell.imageView.image` reference or the `aPhoto.thumbnail` reference? Set a debug breakpoint and check, or better, use `if let photoThumb = aPhoto.thumbnail as? UIImage { }` and make sure it's a valid UIImage. – DonMag May 22 '17 at 13:15
  • Actually `cell.imageView` was having _nil_ value. But Sulthan's answer below solved my problem @DonMag – nayem May 22 '17 at 13:46

2 Answers2

17

There are 3 ways to register a cell (either for UITableView or UICollectionView).

  1. You can register a class. That means the cell has no nib or storyboard. No UI will be loaded and no outlets connected, only the class initializer is called automatically.

  2. You can register a UINib (that is, a xib file). In that case the cell UI is loaded from the xib and outlets are connected.

  3. You can create a prototype cell in the storyboard. In that case the cell is registered automatically for that specific UITableViewController or UICollectionViewController. The cell is not accessible in any other controller.

The options cannot be combined. If you have a cell prototype in the storyboard, you don't have to register again and if you do, you will break the storyboard connection.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • That was what I needed to know. I used the register method (the documentation says you should, the template provides the stub), and all my outlets were nil. Remove the 'necessary' method, and it worked. – green_knight Aug 04 '19 at 18:53
0

You can assign Nib to Collection view cell with an identifier as follows :

self.collectionView.register(UINib(nibName: "nibName", bundle: nil), forCellWithReuseIdentifier: "cell")

Hope it helps.

Balaji Ramakrishnan
  • 1,909
  • 11
  • 22