iosswiftuicollectionviewheaderuicollectionviewlayout

Optional UICollectionView Header


I've implemented the following method in the UICollectionViewDataSource in order to return a header for my UICollectionView section.

However, I'd only like to return a header view if hasOthers is true. The below code throws the following exception in this case:

Exception NSException * "the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath (UICollectionElementKindSectionHeader,<NSIndexPath: 0xaa02564b411fe771> {length = 2, path = 0 - 0}) was not retrieved by calling -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath: or is nil (<UICollectionReusableView: 0x7ff43f577700; frame = (0 0; 0 0); layer = <CALayer: 0x6000026484a0>>)" 0x000060000321f240

I also can't return nil from this method as it doesn't return an Optional.

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    if kind == UICollectionView.elementKindSectionHeader {
        if !hasOthers {
            return UICollectionReusableView()
        }
        if let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "header", for: indexPath) as? OrderCVHeaderView {
            sectionHeader.backgroundColor = .white
            return sectionHeader
        }
    }
    return UICollectionReusableView()
}

I followed this example when implementing:

https://stackoverflow.com/a/57666316/4909000

How can I return an optional header, only if hasOthers is true?


Solution

  • The docs say: This method must always return a valid view object. If you do not want a supplementary view in a particular case, your layout object should not create the attributes for that view. Alternatively, you can hide views by setting the isHidden property of the corresponding attributes to true or set the alpha property of the attributes to 0. To hide header and footer views in a flow layout, you can also set the width and height of those views to 0.