Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What to return from collectionView(_:viewForSupplementaryElementOfKind:at:) when you want to return nothing?

I have a UICollectionView that has section headers, but not section footers. As such, I don't have a defined footer view. Apple's documentation states that You must not return nil from this method.

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    switch kind {
    case UICollectionElementKindSectionHeader:
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
                                                                         withReuseIdentifier: "MyHeaderView",
                                                                         for: indexPath) as! MyHeaderView
        switch indexPath.section
        {
        case 0:
            headerView.label_title.text = "SOME HEADER"
        case 1:
            headerView.label_title.text = "ANOTHER HEADER"
        default:
            headerView.label_title.text = "UNKNOWN HEADER"
        }
        return headerView
    default:
        assert(false, "Unexpected element kind") // Not a good idea either
    }
    return nil // NOPE, not allowed
}
like image 818
GoldenJoe Avatar asked Jun 30 '17 09:06

GoldenJoe


2 Answers

None of the above worked for me. In my case I have two UICollectionView objects in the same view controller. First is horizontal, selecting an item of which displays the below UICollectionView that is vertical and contains section headers.

From Apple docs:

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.

so dequeue the headerView as usual because if you don't and just return an instance of UICollectionReusableView() Xcode will complain the header view is not dequeued. And then if you don't want to display it for some reason (for me until user selects an item from the upper horizontal collection view) - set the width and height of the headerView to 0.0 and return it.

let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: collectionHeaderReuseIdentifier, for: indexPath) 
if objects.isEmpty {
    headerView.frame.size.height = 0.0
    headerView.frame.size.width = 0.0
    return headerView
}
// Configure the header view here if needed
return headerView
like image 63
Ahmed Khedr Avatar answered Sep 20 '22 21:09

Ahmed Khedr


For me personally, if you didn't tell UICollectionView to display section footers then it's not gonna show them. So it's OK to put preconditionFailure in that delegate method.

My thought behinds that is that, UICollectionView won't gonna do things more that you tell it to do. So if you didn't tell UICollectionView to display section footers then it will not show them and it will be safe to have preconditionFailure for those footer views case. But if you find a crash in that case then it's either UIKit bug which you should file a radar for that to tell Apple or it's your bug to ask UICollectionView to display section footer unintentionally.

So my code would look similar to this

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
  switch kind {
  case UICollectionElementKindSectionHeader:
      let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
                                                                     withReuseIdentifier: "MyHeaderView",
                                                                     for: indexPath) as! MyHeaderView
      /* Configure your section header here */
      return headerView
  default:
      preconditionFailure("Invalid supplementary view type for this collection view")
  }
}
like image 36
Pitiphong Phongpattranont Avatar answered Sep 17 '22 21:09

Pitiphong Phongpattranont