Sercan
Sercan

Reputation: 164

How to detect button tap in a UITableViewCell which is in a UICollectionViewCell?

I'm trying to detect button tap in a UITableViewCell which is in a UICollectionViewCell.

UICollectionView's delegate and dataSource is my ViewController. There is one UITableView in every UICollectionViewCell. And the UITableViewCell's delegate and dataSource is the UICollectionViewCell.

I need to detect button taps in the ViewController.

ViewController

@IBOutlet collectionView: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.delegate = self
    collectionView.dataSource = self
}

UICollectionView

@IBOutlet tableView: UITableView!

override func awakeFromNib() {
    super.awakeFromNib()
    tableView.delegate = self
    tableView.dataSource = self
}

UITableViewCell

@IBAction func buttonTapped(_ sender: CustomButton) {
    // Detect Button Tap in ViewController
}

Upvotes: 2

Views: 1781

Answers (2)

fgroeger
fgroeger

Reputation: 422

You could write your own delegate for that.

protocol ButtonDelegate: class {
    func buttonTapped(_ button: UIButton)
}

Then, implement it in your ViewController and do whatever you want to happen when the button gets tapped.

In your UICollectionView and your UITableViewCell, add a property:

weak var buttonDelegate: ButtonDelegate?

And then, modify your UITableViewCell:

@IBAction func buttonTapped(_ sender: CustomButton) {
    buttonDelegate?.buttonTapped(sender)
}

In the ViewController you have to set the delegate on the UICollectionView:

collectionView.buttonDelegate = self

At last, in your cellForRowAt method in your UICollectionView, set the buttonDelegate property of the UITableViewCell to the buttonDelegate of the UICollectionView, which is your ViewController:

cell.buttonDelegate = buttonDelegate

Upvotes: 2

Robert Dresler
Robert Dresler

Reputation: 11140

I would suggest you to use delegate pattern.


So you need one protocol for table view cell and one for collection view cell

protocol TableCellDelegate: class {
     func buttonPressed(_ sender: CustomButton)
}

protocol CollectionCellDelegate: class {
     func buttonInTableCellPressed(_ sender: CustomButton)
}

now create delegate variables for cell subclasses

class TableCell: ... {
    weak var delegate: TableCellDelegate?
}

class CollectionCell: ... {
    weak var delegate: CollectionCellDelegate?
}

continue with implementing TableCellDelegate to CollectionView and call method on cell's delegate inside table cell delegate's method

extension CollectionCell: TableCellDelegate {
    func buttonPressed(_ sender: CustomButton) {
        delegate?.buttonInTableCellPressed(sender)
    }
}

next implement CollectionCellDelegate to your view controller

extension ViewController: CollectionCellDelegate {
    func buttonInTableCellPressed(_ sender: CustomButton) {
        ... // this is called when button in table view cell is pressed
    }
}

Now, don't forget to set delegate of collection cell inside cellForItemAt in ViewController and delegate of table cell inside cellForRowAt in CollectionCell

class ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        ...
        cell.delegate = self
        ...
    }
}

class CollectionCell: UICollectionViewCell, UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        ...
        cell.delegate = self
        ...
    }
}

Now, finally, call method on delegate inside table cell when button is pressed

@IBAction func buttonTapped(_ sender: CustomButton) {
    delegate?.buttonPressed(sender)
}

Upvotes: 3

Related Questions