Eman H Eman H - 3 months ago 24
Swift Question

Setting my Custom Class' Delegate to my View Controller

I created a custom class that is a subclass of

UICollectionReusableView
. It essentially is a Collection View's section header and I'm adding a few buttons on it. When the button is pressed, I want the view controller to filter results (depending on which button is pressed).

I needed my view controller to have an outlet to this custom class, but that did not work because Xcode complains about repeated content having classes (even though I am only going to be using one collectionView section header). So my next option is delegation.

My question is two-fold:


  1. How do I set my custom class' delegate to the view controller? Typically I set the delegate in
    prepareForSegue
    but since I don't have that I'm not sure what to do. My view controller is created in storyboard and my custom class has no reference to it. Even in my View Controller, I cannot access the collection view's section header to set its delegate to self (I checked Apple's documentation and there is no property to access the section header).

  2. When I set up
    IBAction
    s to my custom class, how do I ensure that the button that was tapped is also passed in as the sender? I've connected one of the buttons to an action and wrote
    func someAction (sender: AnyObject) {}
    but how does the program know that the button itself is suppose to be passed in as the sender?



Here is my code:

// Custom Class
class CollectionHeaderView: UICollectionReusableView {

@IBAction func buttonPressed (sender: AnyObject) {
**delegate?.didTapButton(self)**
}
var delegate: UICollectionViewDelegate?
}


// Protocol
protocol CollectionHeaderViewDelegate {
func didTapButton(sender: CollectionHeaderView)
}

// View Controller (the delegate)
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "CollectionHeaderView", forIndexPath: indexPath) as! CollectionHeaderView
headerView.delegate = self
return headerView
}

extension BrowseViewController: CollectionHeaderViewDelegate {
func didTapButton(sender: CollectionHeaderView) {
print("Delegate's Button Tapped")

}
}


The bolded portion is where Xcode gives me an error stating, "Value of type UICollectionViewDelegate has no member 'Did Tap Button'" - not sure why it is referring to the UICollectionViewDelegate..
I tried changing the variable name and the call to tap on the delegate to headerViewDelegate, but it still gave an error.

Answer

If this UICollectionReusableView is a collection view's section header, you can create it in code. You would need to have implemented collectionView:viewForSupplementaryElementOfKind:atIndexPath:. At that point you (the view controller) are creating the section header and can configure it in any way you like.

Alternatively, if this UICollectionReusableView is being created by the flow layout in the storyboard, then put the buttons into it in the storyboard and just connect their actions as you normally would.

enter image description here

but how does the program know that the button itself is suppose to be passed in as the sender

When a button is tapped and its control event action is triggered, the button itself is always provided as the parameter. That's part of what a control is.