Swift - How to detect an action button in UItableViewCell is pressed from ViewController?
You could go for a good old fashioned delegate pattern. This has the advantage of not coupling your view controller from your cell. Don't forget to make your delegate weak
to avoid retain cycles.
The you can find the cell index path from the table view. (I'm assuming by cell number you mean index path)
protocol CellDelegate: class {
func didTap(_ cell: Cell)
}
class Cell: UITableViewCell {
weak var delegate: CellDelegate?
@IBAction func buttonPressed(_ sender: Any) {
delegate?.didTap(self)
}
}
class ViewController: UIViewController, CellDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ...
cell.delegate = self
return cell
}
func didTap(_ cell: Cell) {
let indexPath = self.tableView.indexPath(for: cell)
// do something with the index path
}
}
How to detect button tap in a UITableViewCell which is in a UICollectionViewCell?
You could write your own delegate for that.
protocol ButtonDelegate: class {
func buttonTapped(_ button: UIButton)
}
Then, implement it in your ViewController
and do whatever you want to happen when the button gets tapped.
In your UICollectionView
and your UITableViewCell
, add a property:
weak var buttonDelegate: ButtonDelegate?
And then, modify your UITableViewCell
:
@IBAction func buttonTapped(_ sender: CustomButton) {
buttonDelegate?.buttonTapped(sender)
}
In the ViewController
you have to set the delegate on the UICollectionView
:
collectionView.buttonDelegate = self
At last, in your cellForRowAt
method in your UICollectionView
, set the buttonDelegate
property of the UITableViewCell
to the buttonDelegate
of the UICollectionView
, which is your ViewController
:
cell.buttonDelegate = buttonDelegate
Identify in which table view Cell button was pressed?
Use this line to get indexPath, Where you have to pass UIButton
on target selector
func buttonTapped(_ sender:AnyObject) {
let buttonPosition:CGPoint = sender.convert(CGPointZero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
}
how to distinguish button in tableviewcell click event and tableviewcell click event
I had thought the issue was caused by the layer sequence. Then with the help of @AndreaMugnaini, @FahriAzimov, @MilanNosáľ, I know the layer sequence was not the issue.
Then I think it may caused by the layout. So I check the constraints, I find there is one extra constraint. I removed the 8.5 constraint, it works well.
IOS/Objective-C: Detect Button Press in Custom Tableview Cell?
Instead of using the delegate
or tags
, you can simply use blocks
to do that. Blocks
are much more easy and simple to use than the delegate
pattern and recommended.
In Swift
too, you shall see the extensive use of closures (blocks in Objective-C)
than any other pattern.
Example:
1. UITableViewDataSource
Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
cell.likeButtonTapHandler = ^{
NSLog(@"Like Button Tapped");
//ADD YOUR CODE HERE
};
cell.commentButtonTapHandler = ^{
NSLog(@"Comment Button Tapped");
//ADD YOUR CODE HERE
};
cell.shareButtonTapHandler = ^{
NSLog(@"Share Button Tapped");
//ADD YOUR CODE HERE
};
return cell;
}
2. Custom UITableView Cell
@interface TableViewCell : UITableViewCell
@property (nonatomic, copy) void(^likeButtonTapHandler)(void);
@property (nonatomic, copy) void(^commentButtonTapHandler)(void);
@property (nonatomic, copy) void(^shareButtonTapHandler)(void);
@end
@implementation TableViewCell
- (IBAction)likeButtonTapped:(UIButton *)sender
{
self.likeButtonTapHandler();
}
- (IBAction)commentButtonTapped:(UIButton *)sender
{
self.commentButtonTapHandler();
}
- (IBAction)shareButtonTapped:(UIButton *)sender
{
self.shareButtonTapHandler();
}
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
.
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
Related Topics
How to Check If the iOS Device Is Locked/Unlocked
Handling Private Frameworks in Xcode ≥ 7.3
Class Is Implemented in Both, One of the Two Will Be Used. Which One Is Undefined
How to Distinguish Between Locking the Device and Sending an App to Background
How to Shrink a Uipickerview on the Iphone
Nsdate Beginning of Day and End of Day
How to Set Adaptive Multiline Uilabel Text
iOS 7/Xcode 5: Access Device Launch Images Programmatically
How to Embed Youtube Video on iOS and Play It Directly on Uiwebview Without Full Screen
How to Update a Coredata Entry That Has Already Been Saved in Swift
How to Dynamically Change the Font Size in Auto Layout iOS
Core Audio Offline Rendering Genericoutput
Nsindexpath.Item VS Nsindexpath.Row
Facebook Sdk Login Never Calls Back My Application on iOS 9
Defaultcalendarfornewevents Failed