Swift, iOS15, UIKit, CollectionView header issue

  • I'm having this exact same problem. Here's my error message: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath: does not match the element kind it is being used for. When asked for a view of element kind 'UICollectionElementKindSectionHeader' the data source dequeued a view registered for the element kind 'FeedCollectionViewHeader'.'

Add a Comment

Apple Recommended

Replies

Anyone find a solution to this?

Same problem here:

The view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath: does not match the element kind it is being used for. When asked for a view of element kind 'UICollectionElementKindSectionHeader' the data source dequeued a view registered for the element kind 'UICollectionElementKindSectionFooter

I had the same problem and it was because iOS 15 seems to not support registering the same class for multiple element kinds. I made subclasses of the original class and registered each one for each kind and the crash fixed.

Similar issue with me

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath: was not retrieved by calling -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath: for element kind 'UICollectionElementKindSectionFooter' at index path <NSIndexPath: 0xb271fbe1238032dc> {length = 2, path = 1 - 0}; supplementary view: <UICollectionReusableView: 0x104a6cfb0; frame = (0 0; 0 0); layer = <CALayer: 0x2813ecc80>>'

Hi

If anyone still having same problem, try this:

In my case I faced the problem when I was using list layout

I changed my code from this:

private func createListLayout() -> UICollectionViewLayout {

    var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)

    config.backgroundColor = UIColor.white

    config.headerMode = .supplementary

    let layout = UICollectionViewCompositionalLayout.list(using: config)


    return layout

}

To this code:

 private func createListLayout() -> UICollectionViewLayout {

    let layout = UICollectionViewCompositionalLayout() { sectionIndex, layoutEnvironment in

        var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)

        config.backgroundColor = UIColor.white

        config.headerMode = .supplementary

        let section = NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)

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

        let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(

            layoutSize: headerSize,

            elementKind: "myElementKind", alignment: .top)

        section.boundarySupplementaryItems = [sectionHeader]


        return section
    }


    return layout
}

And this is my provider if you need:

dataSource.supplementaryViewProvider = { (collectionView, kind, indexPath) in

    let header = collectionView.dequeueReusableSupplementaryView(
                               ofKind: "myElementKind",
                               withReuseIdentifier: "myIdentifier",
                               for: indexPath) as! MyCustomHeader

    // code


    return header
}

This worked for me

I hope this works for you as well.

Best regards.

I had the same issue, mostly using IGListKit delegate method:

func viewForSupplementaryElement(ofKind elementKind: String, at index: Int) -> UICollectionReusableView

Instead of using

context.dequeueReusableCell

I changed that call for

context.dequeueReusableSupplementaryView

So the internal IGListKit implementation can use

UICollectionView.dequeueReusableSupplementaryViewOfKind

instead of

UICollectionView.dequeueReusableCellWithReuseIdentifier

That worked for me.

Sorry I forgot to paste the solution I came up with. It should all work now.

enum Section { case main }


var dataSource: UICollectionViewDiffableDataSource<Section, Follower.ID>!

// MARK: - Collection View configurations
    fileprivate lazy var collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: UIHelper.createCompositionalLayout())
        collectionView.delegate = self
        collectionView.backgroundColor = .systemBackground
        collectionView.register(FollowersCollectionHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: FollowersCollectionHeaderView.reuseId)
        view.addSubview(collectionView)
        return collectionView
    }()
    
    fileprivate lazy var snapshot: NSDiffableDataSourceSnapshot<Section, Follower.ID> = {
        var snapshot = NSDiffableDataSourceSnapshot<Section, Follower.ID>()
        snapshot.appendSections([.main])
        let itemIdentifiers = followers.map { $0.id }
        snapshot.appendItems(itemIdentifiers, toSection: .main)
        dataSource.apply(snapshot, animatingDifferences: true)
        return snapshot
    }()
    
    fileprivate func updateData(with followers: [Follower]) {
        snapshot = NSDiffableDataSourceSnapshot<Section, Follower.ID>()
        snapshot.appendSections([.main])
        let itemIdentifiers = followers.map { $0.id }
        snapshot.appendItems(itemIdentifiers, toSection: .main)
        dataSource.apply(snapshot, animatingDifferences: true)
    }
    
    fileprivate func configureDataSource() {
        let cellRegistration = UICollectionView.CellRegistration<FollowerCell, Follower.ID> { [weak self]
            cell, indexPath, followerID in
            guard let self = self else { return }
            
            let followerArray = self.followers.filter { $0.id == followerID }
            
            if let follower = followerArray.first {
                cell.set(on: follower)
            }
        }
        
        dataSource = UICollectionViewDiffableDataSource<Section, Follower.ID>(collectionView: collectionView) {
            collectionView, indexPath, itemIdentifier in
            
            return collectionView.dequeueConfiguredReusableCell(using: cellRegistration,
                                                                for: indexPath,
                                                                item: itemIdentifier)
        }
        
        let headerRegistration = createSectionHeaderRegistration()
        dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in
            return collectionView.dequeueConfiguredReusableSupplementary(using: headerRegistration, for: indexPath)
        }
    }
    
    fileprivate func createSectionHeaderRegistration() -> UICollectionView.SupplementaryRegistration<FollowersCollectionHeaderView> {
        return UICollectionView.SupplementaryRegistration<FollowersCollectionHeaderView>(
            elementKind: FollowersCollectionHeaderView.reuseId) { [weak self] supplementaryView, elementKind, indexPath in
            guard let self = self else { return }
            supplementaryView.set(with: self.user)
        }
    }

This here strangely solved it for me:

lazy var collectionView: UICollectionView = {
    let collectionView = UICollectionView(/**/)
    // ...
     collectionView.register(HeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HeaderView.reuseId)
     collectionView.register(HeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: HeaderView.reuseId)
  // ....
  return collectionView 
}()

And where I reuse the theader:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: HeaderView.reuseId, for: indexPath) as! HeaderView
// ... update header with data
return header 
}

In my collectionView I am only using headers. No footers at all.

I solve this issue. You can see it in stackoverflow