Search code examples
swiftcollectionview

CollectionView Header ReusableView


I have enabled the header in the collectionView through storyboard, then I coded as follows, but Header does not show up. I wonder anyone see any issues?

AskViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()
    askCollectionView.register(AskCollectionViewHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "askCollectionViewHeader")
    askCollectionView.delegate = self
    askCollectionView.dataSource = self
}


extension AskViewController : UICollectionViewDelegateFlowLayout, UICollectionViewDataSource
{
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
     let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "askCollectionViewHeader", for: indexPath) as! AskCollectionViewHeader
     header.askHeaderTitle.text = "Hi"
     return header
    }

    func collectionView(_ collectionView: UICollectionView,
                      layout collectionViewLayout: UICollectionViewLayout,
                      referenceSizeForHeaderInSection section: Int) -> CGSize{
    
        return CGSize(width: view.frame.size.width, height: 200)
    }
}

AskCollectionViewHeader.swift

import UIKit

class AskCollectionViewHeader : UICollectionReusableView {
    
    @IBOutlet weak var askHeaderTitle: UILabel!
}

Solution

  • You are registering a class, but don't have anything that instantiates this view’s askHeaderTitle.

    With collection view headers, you have three options:

    1. Define the reusable view in your storyboard scene (by dragging a “Collection Reusable View” on to your collection view you set up in Interface Builder). In that case, you'd specify the class and the reuse identifier in IB, and you wouldn't call register in viewDidLoad at all, but rather let the storyboard take care of that.

    2. Define the reusable view in a NIB. In that case, you'd register the NIB in IB, not the class.

    3. Define the reusable view programmatically. Only in that case would you use register with the class. But then again, that subclass wouldn't use @IBOutlet (because you aren't defining it in IB), and you'd be creating the subviews programmatically.

    I think option 1 is easiest, but obviously is only applicable if you are using storyboards and cell prototypes. Option 2 is useful if you have some reusable view that you plan on using from multiple view controllers. Option 3 is a technique one might employ if you want to do everything manually.