swiftuicollectionviewuicollectionreusableview

add custom header to collection view swift


I am trying to add header to collectionView using custom xib file. I created the xib file with class implementing UICollectionReusableView. In collectionViewController I registered the xib file like this:

self.collectionView.register(UINib(nibName: HCollectionReusableView.nibName, bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: HCollectionReusableView.reuseIdentifier)

and after that in viewForSupplementaryElementOfKind I did

let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: HCollectionReusableView.reuseIdentifier, for: indexPath) as! HCollectionReusableView

and for sizing

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    return CGSize(width: 100, height: 50)
}

I am getting error: Could not load NIB in bundle. any missing code ?

HCollectionReusableView class:

class HCollectionReusableView: UICollectionReusableView {

static var nibName : String
    {
    get { return "headerNIB"}
}

static var reuseIdentifier: String
    {
    get { return "headerCell"}
}



override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

}


Solution

  • You need to call viewForSupplementaryElementOfKind like this:

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    
        switch kind {
        case UICollectionElementKindSectionHeader:
               let reusableview = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HCollectionReusableView", for: indexPath) as! HCollectionReusableView
    
                reusableview.frame = CGRect(0 , 0, self.view.frame.width, headerHight)
             //do other header related calls or settups
                return reusableview
    
    
        default:  fatalError("Unexpected element kind")
        }
    }
    

    This way you can initialise and show the header

    Another way of setting the UICollectionViewHeader frame is by extending UICollectionViewDelegateFlowLayout like this:

    extension UIViewController: UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
            return CGSize(width: collectionView.frame.width, height: 100) //add your height here
        }
    }
    

    This removes the need to call :

    reusableview.frame = CGRect(0 , 0, self.view.frame.width, headerHight)
    

    in the above mentioned

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
    

    Remember to register the HeaderView after you initialise your UICollectionView by calling:

    collectionView.register(UINib(nibName: HCollectionReusableView.nibName, bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HCollectionReusableView")
    

    Swift 4.1 Update

    UICollectionElementKindSectionHeader has been renamed to UICollectionView.elementKindSectionHeader