UICollectionView: Adding single Tap Gesture Recognizer to supplementary view

I too have not been able to add a gesture to a cell via IB.

However, my experience has been that using IB you CAN add a gesture recognizer to the collectionView itself by dragging one to the collectionView item in the outline view NOT to the scrollView that lies on top of the collectionView in the graphical representation.

So far I can only get a single tap through the cell and into the collectionView.


I add gesture recognizer when the supplementary view has been loaded from nib.

class MySuppleMentaryView: UICollectionReusableView
{

    @IBOutlet var label: UILabel!

    weak var delegate: MySuppleMentaryViewDelegate!

    override func awakeFromNib() {
        super.awakeFromNib()

        // NOTE: UILabel MUST enable user interaction to receive touch events.
        // label.isUserInteractionEnabled = true

        let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel))
        tap.delaysTouchesBegan = true
        tap.numberOfTapsRequired = 1

        self.label.addGestureRecognizer(tap)
    }

    @objc func onClickLabel() {
        self.delegate.didOnLabel(cell: self)
    }
}

protocol MySuppleMentaryViewDelegate: NSObjectProtocol {
    func didOnLabel(cell: DCScheduleHourLabel)
}

// Configure supplementary cell
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

    if (kind == UICollectionElementKindSectionHeader) { 
        // NOTE: The cell might be reused.
        // If gesture recognizer is added HERE, 
        // then maybe multiple gesture recognizers are added when reusing the cell. 
        let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: DCScheduleDummyBlock.Identifier, for: indexPath) as! MySuppleMentaryView

        // configure cell
        cell.delegate = self
        return cell                
    }

    return UICollectionReusableView()
}     

So it looks like you cannot use the interface builder to add a gesture recognizer to a supplementary view of a UICollectionView.

I believe this is because when the .xib's are loaded, the UICollectionView must appear as one thing to the superview -- and when you add the gesture recognizer to that UICollectionView you end up with two things at the superview level, which both correspond to the UICollectionView.

You can however implement your gesture recognizer programmatically using the definition of your supplementary view inside of the UICollectionViewReusableView Protocol. (The if is being used to distinguish between a header supplementary view and an footer supplementary view later in the code)

if (kind == UICollectionElementKindSectionHeader) {
    MyHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"MY_HEADER" forIndexPath:indexPath];

    // call headerView methods (to put things into the header's UI objects for example)
    [headerView ...];
    [headerView ...];
    [headerView ...];

    // add gesture recognition for tapping on a UIlabel within the header (UICollectionView supplementary view)
    UITapGestureRecognizer *bioTap = [[UITapGestureRecognizer alloc] initWithTarget:headerView action:@selector(handleUILabelTap:)];
    // make your gesture recognizer priority
    bioTap.delaysTouchesBegan = YES;
    bioTap.numberOfTapsRequired = 1;
    [headerView.UILabelName addGestureRecognizer:UILabelTap];

    reusableview = headerView;
}