UITableViewCell Buttons with action

uibutton in uitableviewcell click event
add button to uitableviewcell programmatically swift
accessorybuttontappedforrowwith
uitableviewcell button click swift 4
button action in cell objective c
how to get the indexpath.row when a button in a cell is tapped?
button action in cell swift 4
button action inside cell swift 4

Hi I have a custom UITableViewCell with three buttons to handle a shopping cart function, Plus,Minus and Delete button and I need to know which cell has been touched.

I've already tried to use the "tag solution" but it isn't working due to the lifecycle of the cells.

Can anyone please help me find a solution?

Thanks in advance

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.

UIButton action in table view cell, var buttonTappedAction : ((UITableViewCell) -> Void)?. Add an action when the button is pressed that only executes the closure. You did it programmatically with � Interacting with a UIButton To handle the interaction with a button, you can create the IBAction in your view controller as per normal (eg. drag the button action selector to your view controller). The trick is to get the superview of the button, which will be the cell, and then using tableView.indexPathForCell (cell) to get the index path.

I came across the same problem after making the IBOutlets private as has been broadly suggested by the community.

Here is my solution:

< In your cell class >

protocol YourCellDelegate: class {
    func didTapButton(_ sender: UIButton)
}

class YourCell: UITableViewCell {

    weak var delegate: YourCellDelegate?

    @IBAction func buttonTapped(_ sender: UIButton) {
        delegate?.didTapButton(sender)
    }
}

< In your ViewController >

class ViewController: UIViewController, YourCellDelegate {

    func didTapButton(_ sender: UIButton) {
        if let indexPath = getCurrentCellIndexPath(sender) {
            item = items[indexPath.row]
        }
    }

    func getCurrentCellIndexPath(_ sender: UIButton) -> IndexPath? {
        let buttonPosition = sender.convert(CGPoint.zero, to: tableView)
        if let indexPath: IndexPath = tableView.indexPathForRow(at: buttonPosition) {
            return indexPath
        }
        return nil
    }
}

Handling button tap inside UITableView Cell without using tag, addTarget(self, action: #selector(subscribeTapped(_:)), for: .touchUpInside) return cell } @objc func subscribeTapped(_ sender: UIButton){� Tapping one of the action buttons executes the handler block stored with the action object. This method returns an array of UITableViewRowAction objects representing the actions for the row. Each action you provide is used to create a button that the user can tap. Here’s what it looks like when a user swipes across the cell.

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 
  }
}

UIButton in UITableViewCell using Delegates and Protocols in Swift , In this Swift Tutorial, I'll show you how to properly implement buttons UIButton in Duration: 9:54 Posted: Apr 12, 2017 The action will be invoked when the switch value changes. TapActionRow. A TapActionRow is representing a button-like table view cell. The action will be invoked when the table view cell is selected. The icon, detail text, and accessory type are disabled in TapActionRow. OptionRow. An OptionRow is representing a table view cell with .checkmark.

SWIFT 4.*

It can be done like following way too, Not required much coding and delegation, Simple and easy.

Put following code in cellForItemAt for UICollectionView or in cellForRowAt for UITableView

cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)

And your Method will be

@objc func buttonSelected(sender: UIButton){
    print(sender.tag)
}

Thats all.

How to add a button to a UITableViewCell, The second step is to take action when the button is tapped by creating the override func tableView(_ tableView: UITableView,� If you specify a selector for the accessory action, a message is sent only if the accessory view is a detail disclosure button—that is, the cell's accessoryType property is assigned a value of UITableViewCellAccessoryDetailDisclosureButton. If the value of this property is NULL, no action message is sent. The accessory view is a UITableViewCell -defined control, framework control, or custom control on the right side of the cell.

@pedrouan is great, except using button's tag option. In many cases, when you set button on tableViewCell, those buttons will modify tableView dataSource.(e.g. InsertRow, DeleteRow).

But the tag of the button is not updated even if a new cell is inserted or deleted. Therefore, it is better to pass the cell itself as a parameter rather than passing the button's tag to the parameter.

Here is my example to achieve this.

Your ExampleCell

protocol ExampleCellDelegate: class {
    func didTapButton(cell: ExampleCell)
}

class ExampleCell: UITableViewCell {

    weak var cellDelegate: ExampleCellDelegate?

    @IBAction func btnTapped(_ sender: UIButton) {
        cellDelegate?.didTapButton(cell: self)
    }
}

Your ViewController

class ViewController: ExampleCellDelegate {
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as? ExampleCell {

            cell.cellDelegate = self
            return cell
        }
        return UITableViewCell()
    }

    func didTapButton(cell: ExampleCell) {
        if let indexPath = tableView.indexPath(for: cell) {
            // do Something
        }
    }
}

Custom tableview cell, In this post we discussing how to handle button action in custom cell and func tableView(_ tableView: UITableView, cellForRowAt indexPath:� The SWTableViewCellDelegate protocol provides optional methods to manage the action of the utility buttons. If you read the code in the previous section carefully, you should notice the SwipeTableViewController is assigned as the delegate of the SWTableViewCell. We’ll then implement these two methods in the SwipeTableViewController.m:

UIButtons and UIControls in UITableViewCell made easy, In order to communicate which particular cell's button was tapped, a programmer STKTableViewCell simplifies using target-action pairs in UITableViewCells. In this Swift Tutorial, I'll show you how to properly implement buttons in UITableViewCells in Xcode. We'll do this using Delegates and Protocols in Swift. Delegates can be a tricky concept when

How to Handle Button/views Interaction in a UITableViewCell , drag the button action selector to your view controller). The trick is to get the superview of the button, which will be the cell, and then using� Overview. A UITable View Cell object is a specialized type of view that manages the content of a single table row. You use cells primarily to organize and present your app’s custom content, but UITable View Cell provides some specific customizations to support table-related behaviors, including:

UITableViewCell Button : swift, I have buttons set up within my custom UITableViewCell in a table view. How would I make it so that when a button is pressed on a cell, it triggers … On you button, make the cell subclass the target and connect it to an action in the cell subclass. When the user presses the button, you should now run the action in the cell. However, you probably want to execute a function in the view controller. So, make the view controller a delegate of the cell.

Comments
  • Please provide some code of how exactly you're using tags. If you set them in cellForRowAtIndexPath every time a cell is reused , there should not be any problems with lifecycle.
  • This solution seems to be amazing, but I still need to know which cell I've pressed, and when using the tag argument the problem is still the same
  • You may only need to add a connection between the button from the cell and the IBAction buttonPressed() method typed in the step 2)
  • The cell.tag = indexPath.row just gives me 0 for all rows. Shouldn't the sender.tag in step 2 be self.tag, since it is the cell's tag you set to indexPath.row in step 4. Using self.tag instead of sender.tag in step 2 works as expected for me.
  • How do you resolve the section part of cell's index path in case the tableview implements also sections?
  • To handle multiple section give your cell an indexPath var and set that instead of using tag.
  • Your solution should be the one accepted. It also works without using a delegation pattern for the UITableViewCell subclass when configuring the cell's button to be tied to an action of a view controller.
  • So much nicer to not use .tag property and so much cleaner!
  • Another way instead of convert points is to use superview to get the cell and then call indexPath(for: UITableViewCell)
  • you forgot cell.delegate = self in cellforrowatindexpath.
  • Thank you @DeyaEldeen - that is the only other thing needed.
  • thanks @RimK its working fine +1 up for this solution
  • This is the only correct answer that includes best practices, which is funny because it has zero upvotes. Just look at examples like UITableViewDelegate for guidance. You should be passing the cell itself in the delegate method. Then, in your controller for example, you can fetch the index path for the cell, which can then be used to access the correct data in your data source via indexPath.row. Relying on a primitive like tag makes no sense and is bound to break.
  • This is a good solution but strongly thighed to how the view is designed. In case the button lies in another subview (as for example a stack view), you'd might get with a long list of superview calls to detect the cell where the button lies in.