Collection Reusable View Added Via Storyboard Not Registering with the Collection View

When I set up a UICollectionReusableView cell in storyboard and try to dequeue a cell of this type, my app crashes with this error message:

Steps I've gone through to add my collection reusable view in storyboard:

  1. I added a collection reusable view by dragging the item from the panel of objects to my collection view.
  2. I created a class called EmotionFiltersHeaderView which subclasses UICollectionReusableView that contains a reference to an IBOutlet var for the label I added to the reusable view (also in storyboard).
  3. I changed the class name of the reusable view in the storyboard to my custom class name, EmotionFiltersHeaderView.
  4. I added an identifier to the reusable view and called it "emotionFiltersHeaderReusableView".
  5. I've included the header view in the boundary supplementary items property of the section where I'm adding the header view.

This is my code:

`let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(37.0))

        let header = NSCollectionLayoutBoundarySupplementaryItem(
            layoutSize: headerSize,
            elementKind: UICollectionView.elementKindSectionHeader,
            alignment: .topLeading)
        
        section.boundarySupplementaryItems = [header]

    emotionFiltersDataSource.supplementaryViewProvider = { collectionView, kind, indexPath in
      guard let headerView = collectionView.dequeueReusableSupplementaryView(
        ofKind: ElementKind.sectionHeader.rawValue,
            withReuseIdentifier: "emotionFiltersHeaderReusableView",
            for: indexPath
      ) as? EmotionFiltersHeaderView else {
          fatalError("Could not dequeue header view as EmotionFiltersHeaderView")
      }
        
        let sectionTitle = Section.allCases[indexPath.section].rawValue
        headerView.sectionTitleLabel.text = sectionTitle
        return headerView
    }

enum ElementKind: String { case sectionHeader = "section-header-element-kind" }`

Answered by BabyJ in 847199022

Assuming the supplementary view has been registered properly, then the only other thing I see is that the element kind strings are mismatched.

In your layout, you are specifying the elementKind as UICollectionView.elementKindSectionHeader (which is the string "UICollectionElementKindSectionHeader").

But when you dequeue the view, you are requesting it be of kind ElementKind.sectionHeader.rawValue ("section-header-element-kind").

I think this might be the cause of the crash.

Accepted Answer

Assuming the supplementary view has been registered properly, then the only other thing I see is that the element kind strings are mismatched.

In your layout, you are specifying the elementKind as UICollectionView.elementKindSectionHeader (which is the string "UICollectionElementKindSectionHeader").

But when you dequeue the view, you are requesting it be of kind ElementKind.sectionHeader.rawValue ("section-header-element-kind").

I think this might be the cause of the crash.

Thanks @BabyJ. I have updated my code to address the discrepancy which you've noted. My code now looks like this:

` let section = NSCollectionLayoutSection(group: group)

        let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                                heightDimension: .estimated(37.0))
        
        let header = NSCollectionLayoutBoundarySupplementaryItem(
            layoutSize: headerSize,
            elementKind: ElementKind.sectionHeader.rawValue,
            alignment: .topLeading)
        
        section.boundarySupplementaryItems = [header]

    emotionFiltersDataSource.supplementaryViewProvider = { collectionView, kind, indexPath in
      guard let headerView = collectionView.dequeueReusableSupplementaryView(
        ofKind: ElementKind.sectionHeader.rawValue,
            withReuseIdentifier: "emotionFiltersHeaderReusableView",
            for: indexPath
      ) as? EmotionFiltersHeaderView else {
          fatalError("Could not dequeue header view as EmotionFiltersHeaderView")
      }
        
        let sectionTitle = Section.allCases[indexPath.section].rawValue
        headerView.sectionTitleLabel.text = sectionTitle
        return headerView
    }

But I am still seeing the error.

I had also selected the Section header accessory in the storyboard, but I've now deselected it when I tried using your suggestion and have gotten the same crash as before.

I'm having trouble reproducing the crash. What does your storyboard look like? You are using a UICollectionView with a custom layout (UICollectionViewCompositionalLayout by the looks of it). You have a subclass of UICollectionReusableView set as a header for the custom layout.


According to the error message:

must register a nib or a class for the identifier or connect a prototype cell in a storyboard

I think this might be the other issue you are having. You can either manually register your custom class, like this:

collectionView.register(
    EmotionFiltersHeaderView.self, 
    forSupplementaryViewOfKind: ElementKind.sectionHeader.rawValue,
    withReuseIdentifier: "emotionFiltersHeaderReusableView"
)

Or connect the reusable view in the storyboard (whatever that means). I would try manually registering first and see if that works.



I'm not a fan of using storyboards, especially when working with collection views. With the introduction of compositional layouts, diffable data sources, and modern cell registrations — all designed to be configured in code — combining them with storyboards just turns into a mess, and results in error messages like yours. That's just my opinion though.

Apologies @BabyJ , I implemented the collectionView.register method which resulted in the cell dequeuing correctly, but my label in my header view was appearing nil which caused the application to crash. So I went back to your original answer and I updated the kind to UICollectionView.elementKindSectionHeader, and this worked, dequeuing the header successfully and supplying the label I added in storyboard in the reusable view. I believe that when implementing a collection reusable view in storyboard, I need to use UICollectionView.elementKindSectionHeader because this returns the object with the views in the storyboard.

Collection Reusable View Added Via Storyboard Not Registering with the Collection View
 
 
Q