1

I want to implement UITableView Where I want to have 3 buttons in each UITableViewCell. I want to perform a diffeent action for each button. How can I identify which button is bring pressed and then get the object(index row ) of the cell that was selected?

UIViewController

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let show=shows[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "ShowCell") as!
    ShowCell

    cell.setShow(show: show)
    return cell
}

UITableViewCell

@IBOutlet weak var graphButton: FlatButton!
@IBOutlet weak var buyButton: FlatButton!
@IBOutlet weak var reviewButton: FlatButton!


func setShow(show :StubHubEvent ){


    let url = URL(string: show.imageurl)!

    showImageView.af_setImage(withURL: url)
    showImageView.contentMode = .scaleAspectFill
    showImageView.clipsToBounds = true
    nameLabel.text = show.title
    dateLabel.text = show.time
Anbu.Karthik
  • 82,064
  • 23
  • 174
  • 143
user1163234
  • 2,407
  • 6
  • 35
  • 63

2 Answers2

3

implement your button action in UIviewcontroller not a UITableViewCell, create the target in inside the cellforRow as well as add the Tag for each target for identify which button was user pressed.for E.g

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let show=shows[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "ShowCell") as!
    ShowCell

     cell.graphButton.tag = indexPath.row
     cell.buyButton.tag = indexPath.row
     cell.reviewButton.tag = indexPath.row

     cell.graphButton?.addTarget(self, action: #selector(self.graphButtonClicked(_:)), for: .touchUpInside)
     cell.buyButton?.addTarget(self, action: #selector(self.buyButtonClicked(_:)), for: .touchUpInside)          
     cell.reviewButton?.addTarget(self, action: #selector(self.reviewButtonClicked(_:)), for: .touchUpInside)


    cell.setShow(show: show)
    return cell
}

and handle the action as like

 @objc func buyButton( _ sender: UIButton) {
       print("buyButton Action Found the index of \(sender.tag)")

}

@objc func graphButtonClicked( _ sender: UIButton) {
       print("graphButtonClicked Action Found the index of \(sender.tag)")

}

@objc func reviewButtonClicked( _ sender: UIButton) {
       print("reviewButtonClicked Action Found the index of \(sender.tag)")

}

Option 2

if you want to perform in your button action in UItableviewcell class using delegate pattern, then refer this duplicate answer

Anbu.Karthik
  • 82,064
  • 23
  • 174
  • 143
0

there are two ways to get button click execution in the ViewController from TableViewCell

  1. Use Delegate pattern
  2. Use blocks as callbacks and handle block execution in the cellForRow method
  3. Add addTarget(:) to add a target method for the button click

Details:

  1. The first approach is best among all the three mentioned approaches, in this, you need to create a delegate which redirects your user actions from cell to view controller. Check below code example.
  2. The second approach is similar to the first one, it just redirects the same method calls using the blocks instead of Delegate methods and protocol.
  3. The third approach is not good, as it is tightly coupled with the indexPath.row value, in the software development industry

Cohesion should be high, Coupling should be low.

Code of first Approach:

//MARK:- Model - StubHubEvent
class StubHubEvent {
  //you model class implementation
}

//MARK:- Protocol - ShowCellUIInteractionDelegate - used to redirect user actions from cell to viewController
protocol ShowCellUIInteractionDelegate: AnyObject {
  func showCell(cell: ShowCell, didTapBuyFor show: StubHubEvent)
  func showCell(cell: ShowCell, didTapGraphFor show: StubHubEvent)
  func showCell(cell: ShowCell, didTapReviewFor show: StubHubEvent)
}

//MARK:- Cell-  ShowCell
class ShowCell: UITableViewCell {

  var show: StubHubEvent!
  weak var delegateUIInteraction: ShowCellUIInteractionDelegate?


  func setShow(show :StubHubEvent ){
    self.show = show
    //your other setup
  }

  //Bind these three action from cell to buttons as a .touchUpInside event
  @IBAction func buttonBuyDidTap( _ sender: UIButton) {
    self.delegateUIInteraction?.showCell(cell: self, didTapBuyFor: self.show)
  }

  @IBAction func buttonGraphDidTap( _ sender: UIButton) {
    self.delegateUIInteraction?.showCell(cell: self, didTapGraphFor: self.show)
  }

  @IBAction func buttonReviewDidTap( _ sender: UIButton) {
    self.delegateUIInteraction?.showCell(cell: self, didTapReviewFor: self.show)
  }
}

//MARK:- ViewController - ShowListingViewController
class ShowListingViewController: UIViewController {
  //you ShowListingViewController implementation
}
//MARK:- Extension - ShowCellUIInteractionDelegate
extension ShowListingViewController: ShowCellUIInteractionDelegate {
  //execute your logic for the show model object
  func showCell(cell: ShowCell, didTapBuyFor show: StubHubEvent){

  }
  func showCell(cell: ShowCell, didTapGraphFor show: StubHubEvent){

  }
  func showCell(cell: ShowCell, didTapReviewFor show: StubHubEvent){

  }
}
Hitendra Solanki
  • 4,871
  • 2
  • 22
  • 29