Home > Net >  Crash in CollectionView For Invalid Header
Crash in CollectionView For Invalid Header

Time:11-21

I want to understand what this error means?

 *** 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 'UICollectionElementKindSectionHeader' at index path <NSIndexPath: 0x8aeb905cf5be0ed2> 
{length = 2, path = 0 - 0}; supplementary view: 
<UICollectionReusableView: 0x7f9236dc4ff0; frame = (0 0; 0 0); layer = <CALayer: 0x600001018620>>'

I am using custom header for UICollectionView.I am getting this crash as soon as the view is loaded. even before cellforrowatindexpath is called and the issue is not with the custom header, it is with the return UICollectionReusableView()

func collectionView(_ collectionView: UICollectionView,   viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    
    if kind == UICollectionView.elementKindSectionHeader  && indexPath.section == 2      
    { 
     return someCustomHeader
    }
    
    return UICollectionReusableView()
}
    

CodePudding user response:

You must always obtain the section header with the method dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:, before calling it you must also register a header class. If you want to show only the header of the third section you must implement collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) to hide unwanted headers by giving them a .zero size (you can' t simply return an instance of UICollectionReusableView for unwanted headers).

import UIKit

class CollectionViewController: UICollectionViewController {
   private let headerId = "headerId"

   override func viewDidLoad(){
      super.viewDidLoad()

      // Registers a header class
      self.collectionView.register(YourClass.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: self.headerId)  // Replace YourClass with the name of your header class
   }

   func collectionView(_ collectionView: UICollectionView,   viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
      // This method must always call dequeueReusableSupplementaryView, even if section!=2
      if kind == UICollectionView.elementKindSectionHeader{ 
         return self.collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: self.headerId, for: indexPath)
      }

      return UICollectionReusableView()
    }
   
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize{
       // Shows only the header of the third section
       return section == 2 ? desiredSize : .zero  // Replace desiredSize with the size of the visible header
    }
}

CodePudding user response:

When you work with custom header you have to register first the header class.

  collectionView.register(AppHeaderCollectionView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: AppHeaderCollectionView.headerIdentifier)

and after that for use the header you have to do it this.

 override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: AppHeaderCollectionView.headerIdentifier, for: indexPath) as! AppHeaderCollectionView
        return header
    }
  • Related