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
Why Is the Tab Bar Disappearing
Swift - Json Error: the Data Couldn'T Be Read Because It Isn'T in the Correct Format
Redirect to Application If Installed, Otherwise to App Store
How to Add Spacing Between Uitableviewcell
How to Create Custom Calendar in React Native
How to Remove Constraints Programmatically That Is Added from Storyboard
Create Tap-Able "Links" in the Nsattributedstring of a Uilabel
Ios Swift - Objective C Code Migration to Swift
Firebase Custom Event Parameters Not Visible in Console
How to Display 3 Cells Per Row in Uicollectionview
Nsdictionary to Nsdata and Nsdata to Nsdictionary in Swift
How to Prevent Tableview Section Head from Sticking While Scrolling
Wkwebview Origin Null Is Not Allowed by Access-Control-Allow-Origin
Wkwebview Not Loading Webpage - Renders Blank Screen in Swift