Wednesday, March 04, 2015

Reason Why Your Storyboard Defined UICollectionViewCells Are Blank on Run

TL;DR Remove the / do not add a call to... self.collectionView.registerClass in viewDidLoad
Versions: OS X 10.10.2 Xcode 6.1.1 iOS SDK 8.0
Blank Collection ViewWhen you run your app to see your collection view, does it look like this? 
This isn’t your first rodeo, you’ve implemented UICollectionView before, but maybe it’s been a while.
You want to do it The Right Way™, using all the modern stuff like Storyboards, and then this happens!
What's gone wrong?
You have what seems like a reasonable line of code in viewDidLoad that UICollectionView is choking on!

How You Could Have Got Here...

Let’s say you created a UICollectionViewController in a Storyboard or a UICollectionView in a plain old UIViewController. You’re confident, not cocky, but you know Apple’s pattern on this pretty well, so you go ahead and customize the first cell, nothing that requires code, and then add a second cell that you expect to set properties on, so it might look like this:
Screen Shot 2015 02 27 at 7 44 19 AM

Best Way To Add Code for Storyboard?
Back in the day when Interface Builder was a separate app (pre Xcode 4), there was an option to auto generate class files right from within the UI. If memory serves, this would create the class file as mostly what you wanted and connected to IBActions and IBOutlets.
Since Xcode 4, you can drag actions and outlet into your source code, but the source files have to already exist. If you want to create source, the only way I can find is from the process on the left. There's some typing & option choosing which are needless because you already made those choices in your Storyboard. Worse, the source is not customized in any way from the changes you already made in the Storyboard.
Anyone have a less manual way? Let me know, I can't seem to find one.
Now you think it’s time to add code for the view controller you created in the storyboard, so you go through the File -> New -> File (or ⌘N if you do this a lot) dialogs like in the screenshots below: (your mileage may vary with different Xcode versions)
 Screen Shot 2015 02 27 at 8 00 03 AM Screen Shot 2015 02 27 at 7 56 17 AM

 

The code template that's used for a UICollectionViewController seems like a reasonable starting point. It adds the following line to viewDidLoad:
Obj-C [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
Swift self.collectionView!.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)


If you've customized the stock UICollectionViewCell in your Storyboard, the cell with the matching reuse identifier in code will cause UICollectionView to load an empty UICollectionViewCell! If you went full steam ahead and added a bunch of custom cells with matching reuse identifiers and registerCell calls in viewDidLoad, you, ah, might not figure this one out for a while.