I'm trying to do something very similar to How to make a simple collection view with Swift (with a storyboard), the only difference being that I want to use a diffable datasource, whereas in the linked question, the poster is using a "conventional" dataSource. (that linked question is really a tutorial phrased as a question).
I've placed a UICollectionView onto a storyboard viewcontroller, connected the collectionView to an outlet, and dataSource and delegate to the view controller, and, in my subclass of UICollectionViewCell, created an outlet connected to a label in the storyboard collectionview cell.
I have two problems.
I create a cell registration using .CellRegistration..., and in the CellRegistration closure I try to set the cell's label to either a constant, or a value from the dataSource. This crashes with a 'Unexpectedly found nil while implicitly unwrapping an optional. Somehow the label, which I was expecting to be accessible, is nil.
If I comment out the offending lines, the code runs. But the display shows me a number of empty cells corresponding exactly to the number of items in my dataSource. It does NOT, as I expected, show a series of my cells with my label. (The collectionview on the storyboard is set to flow. If I set it to custom, the display shows an empty collectionView, no sign of any cells. I've briefly experimented with creating a layout, which kinda worked, but still no sign of my cells and label. So I set the storyboard layout back to flow and removed the layout code from the code below).
While composing this, I came across Subclassed UICollectionViewCell is not displaying, and the comment by @Fogmeister caught my eye. It says there is no need to "register" the class or the nib, because that overrides the storyboard. Now I'm not doing that exactly, but maybe the "Cellregistration" I am doing is somehow related?
Here is my code, all in one file.
import UIKit
class ViewController: UIViewController {
let reuseIdentifier = "UgosCell" // matches the identifier for the collection view cell on the storyboard
@IBOutlet weak var ugosCollectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Int, String>! = nil
override func viewDidLoad() {
super.viewDidLoad()
configureDataSource()
seedDataSource()
}
private func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UgosCollectionViewCell, String> { (cell, indexPath, item) in
if indexPath.row == 0 {
print("ROW 0")
cell.lLabel.text = "Header Header" //RUNTIME CRASH
cell.backgroundColor = .purple //if flow layout, this appears
} else {
print("ROW OTHER THAN 0")
cell.lLabel.text = item //RUNTIME CRASH
cell.backgroundColor = .systemPink // if flow layout this appears
}
} // end closure
dataSource = UICollectionViewDiffableDataSource<Int, String>(collectionView: ugosCollectionView) { (collectionView, indexPath, item) -> UgosCollectionViewCell? in
let cell = collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item )
return cell
} // end closure
}
func seedDataSource() {
var sectionSnapshot = NSDiffableDataSourceSectionSnapshot<String>()
sectionSnapshot.append(["HEADER"])
sectionSnapshot.expand(["HEADER"])
sectionSnapshot.append(["A", "B", "C", "D", "E", "F", "G","H", "I", "J", "K", "L", "M"], to: "HEADER")
print("\(sectionSnapshot.visualDescription())")
dataSource.apply(sectionSnapshot, to: 0)
}
}
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
}
}
class UgosCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var lLabel: UILabel!
}
I've put traces in the code and saw that the datasource does indeed get asked for (and returns) as many cells as there are items in the datasource. But again I don't know how to then put any of the data into the collectionview cell's label?
Here's the storyboard
If I remove the registration, the dequeueConfiguredReusableCell(... statement won't compile as there is no cell registration.
And here the connections:
And finally the output:
Update 1: Regarding the "registration", I've now seen several comments to the related question saying that when using a storyboard, there should not be any code to register the custom cell with the collection view. Which I imagine would look as follows:
self.ugosCollectionView.register(UgosCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
This was never in my code, but out of an abundance of curiosity, I tried adding it into the viewDidLoad function, just to see what would happen. Alas, nothing.

