Get Button Click Inside Uitableviewcell

UIButton action in table view cell

Swift 4 & Swift 5:

You need to add target for that button.

myButton.addTarget(self, action: #selector(connected(sender:)), for: .touchUpInside)

And of course you need to set tag of that button since you are using it.

myButton.tag = indexPath.row

You can achieve this by subclassing UITableViewCell. Use it in interface builder, drop a button on that cell, connect it via outlet and there you go.

To get the tag in the connected function:

@objc func connected(sender: UIButton){
let buttonTag = sender.tag
}

Get button click inside UITableViewCell

1) In your cellForRowAtIndexPath: method, assign button tag as index:

cell.yourbutton.tag = indexPath.row;

2) Add target and action for your button as below:

[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

3) Code actions based on index as below in ViewControler:

-(void)yourButtonClicked:(UIButton*)sender
{
if (sender.tag == 0)
{
// Your code here
}
}

Updates for multiple Section:

You can check this link to detect button click in table view for multiple row and section.

Handle button click inside UITableViewCell

The way I handle buttons inside custom cells:

  • I define an IBAction that I connect to a UIButton event inside the custom cell
  • I define a delegate and a delegate method for the cell to handle the button action
  • The IBAction calls that delegate method
  • When defining your cells in cellAtRow... I set the tableViewController to be the delegate. cell.delegate=self;
  • I do whatever action I would like to do inside that delegate method in the tableViewController

Makes sense?

get indexPath of UITableViewCell on click of Button from Cell

Use Delegates:

MyCell.swift:

import UIKit

//1. delegate method
protocol MyCellDelegate: AnyObject {
func btnCloseTapped(cell: MyCell)
}

class MyCell: UICollectionViewCell {
@IBOutlet var btnClose: UIButton!

//2. create delegate variable
weak var delegate: MyCellDelegate?

//3. assign this action to close button
@IBAction func btnCloseTapped(sender: AnyObject) {
//4. call delegate method
//check delegate is not nil with `?`
delegate?.btnCloseTapped(cell: self)
}
}

MyViewController.swift:

//5. Conform to delegate method
class MyViewController: UIViewController, MyCellDelegate, UITableViewDataSource,UITableViewDelegate {

//6. Implement Delegate Method
func btnCloseTapped(cell: MyCell) {
//Get the indexpath of cell where button was tapped
let indexPath = self.collectionView.indexPathForCell(cell)
print(indexPath!.row)
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as! MyCell
//7. delegate view controller instance to the cell
cell.delegate = self

return cell
}
}

How to identify click from multiple buttons in a UITableViewCell from a UITableView - Swift 4

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

Swift - Clicked button inside tableview cell does not call the did select row at function of that cell

Button action won't call the didSelectRowAt. You should go for delegate method. If not aware about delegate means refer this

How to add a button with click event on UITableViewCell in Swift?

Popular patterns for solving this problem are closures and delegates.
If you want to use closures, you would do something like this:

final class MyCell: UITableViewCell {
var actionBlock: (() -> Void)? = nil

then

    @IBAction func didTapButton(sender: UIButton) {
actionBlock?()
}

then in your tableview delegate:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell
cell?.actionBlock = {
//Do whatever you want to do when the button is tapped here
}

A popular alternative is to use the delegate pattern:

    protocol MyCellDelegate: class {
func didTapButtonInCell(_ cell: MyCell)
}

final class MyCell: UITableViewCell {
weak var delegate: MyCellDelegate?

then

    @IBAction func didTapButton(sender: UIButton) {
delegate?.didTapButtonInCell(self)
}

..
Now in your view controller:

then in your tableview delegate:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell
cell?.delegate = self

And add conformance to the protocol like this:

extension MyViewController: MyCellDelegate {
didTapButtonInCell(_ cell: MyCell) {
//Do whatever you want to do when the button is tapped here
}
}

Hope this helps!

Accessing all the cells when a button in a cell is clicked

You can create a closure in custom UITableViewCell and call it whenever a button is pressed in the cell, i.e.

class TableViewCell: UITableViewCell {
@IBOutlet weak var button: UIButton!
var handler: (()->())?

@IBAction func buttonClicked(_ sender: UIButton) {
handler?()
}
}

Now, set the closure in tableView(_:cellForRowAt:) method and use visibleCells property to enable/disable the buttons in other cells, i.e.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.textLabel?.text = arr[indexPath.row]
cell.handler = {
if let visibleCells = tableView.visibleCells as? [TableViewCell] {
visibleCells.forEach({
$0.button.isEnabled = ($0 === cell)
})
}

}
return cell
}

In case you want to persist the enable/disable button states while reloading, you need to store in your model.



Related Topics



Leave a reply



Submit