UITableViewCell Buttons with action

I was resolving this using a cell delegate method within UITableViewCell's subclass.

Quick overview:

1) Create a protocol

protocol YourCellDelegate : class {
    func didPressButton(_ tag: Int)
}

2) Subclass your UITableViewCell (if you haven't done so):

class YourCell : UITableViewCell
{
     var cellDelegate: YourCellDelegate?   
      @IBOutlet weak var btn: UIButton!
    // connect the button from your cell with this method
    @IBAction func buttonPressed(_ sender: UIButton) {
        cellDelegate?.didPressButton(sender.tag)
    }         
    ...
}

3) Let your view controller conform to YourCellDelegate protocol that was implemented above.

class YourViewController: ..., YourCellDelegate {  ... }

4) Set a delegate, after the cell has been defined (for reusing).

let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! YourCell
cell.cellDelegate = self
cell.btn.tag = indexPath.row

5) In the same controller (where is your implemented UITableView delegate/datasource), put a method from YourCellDelegate protocol.

func didPressButton(_ tag: Int) {
     print("I have pressed a button with a tag: \(tag)")
}

Now, your solution is not tag / number dependent. You can add as many buttons as you want, so you are ready to get response via delegate regardless how many buttons you want to install.

This protocol-delegate solution is preferred in iOS logic and it can be used for other elements in table cell, like UISwitch, UIStepper, and so on.


swift 4.2

You can also use closures instead of delegates

1) In your UITableViewCell :

 class ExampleCell: UITableViewCell {
    //create your closure here  
         var buttonPressed : (() -> ()) = {}

        @IBAction func buttonAction(_ sender: UIButton) {
    //Call your closure here 
            buttonPressed()
        }
    }

2) In your ViewController

class ViewController:  UIViewController,  UITableViewDataSource, UITableViewDelegate {
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
   cell.buttonPressed = {
          //Code
           }
return cell 
  }
}