So, the sample app is misusing the API and triggering an assert UIKit added in iOS 15 to catch this.
The sample is incorrectly currently using the same boundary supplementary (therefore the same elementKind) to create multiple supplementary registrations with different classes and elementKinds.
Each NSCollectionLayoutBoundarySupplementaryItem
must have a unique element kind. Similarly, each UICollectionView.SupplementaryRegistration
must have an elementKind matching the appropriate NSCollectionLayoutBoundarySupplementaryItem
.
Concretely, this is what it would look like:
let sectionProvider = { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let headerFooterSize = NSCollectionLayoutSize(...)
switch sectionIndex {
case 0:
let section = NSCollectionLayoutSection(...)
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize, elementKind: "text", alignment: .topLeading)
section.boundarySupplementaryItems = [header]
return section
case 1:
let section = NSCollectionLayoutSection(...)
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize, elementKind: "picture", alignment: .topLeading)
section.boundarySupplementaryItems = [header]
return section
case 2:
let section = NSCollectionLayoutSection(...)
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize, elementKind: "fancyHeader", alignment: .topLeading)
section.boundarySupplementaryItems = [header]
return section
default:
return nil
}
}
Then, when configuring your data source, you'd do this:
let datasource = UICollectionViewDiffableDataSource<Foo, Bar>(...)
let textHeaderRegistration = UICollectionView.SupplementaryRegistration<TextHeaderSupplementaryView>(elementKind: "text") { (supplementaryView, string, indexPath) in
...
}
let pictureHeaderRegistration = UICollectionView.SupplementaryRegistration<PictureHeaderSupplementaryView>(elementKind: "picture") { (supplementaryView, string, indexPath) in
...
}
let fancyHeaderRegistration = UICollectionView.SupplementaryRegistration<PictureSupplementaryView>(elementKind: "fancyHeader") { (supplementaryView, string, indexPath) in
...
}
datasource.supplementaryViewProvider = { [weak self] (view, kind, indexPath) in
guard let self = self else { return nil }
switch indexPath.section {
case 0:
return self.collectionView.dequeueConfiguredReusableSupplementary(using: textHeaderRegistration, for: index)
case 1:
return self.collectionView.dequeueConfiguredReusableSupplementary(using: pictureHeaderRegistration, for: index)
case 2:
return self.collectionView.dequeueConfiguredReusableSupplementary(using: fancyHeaderRegistration, for: index)
default:
return nil
}
}
Note how the element kinds for the boundary supplementary items, the registrations, and the dequeued supplementaries all match. We will also update the sample to fix the crash and correctly use UIKit's API.