Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 415 Vote(s) - 3.4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Get button click inside UITableViewCell

#1
I have a view controller with a table view and a separate nib for the table cell template. The cell template has some buttons. I want to access the button click along with the index of the cell clicked inside the view controller where I have defined the Table view.

So I have `ViewController.h` and `ViewController.m` where I have the `UITableView` and `TableTemplate.h`, `TableTemplate.m` and `TableTemplate.xib` where I have the nib defined. I want the button click event with cell index in `ViewController.m`.

Any help on how can I do that?
Reply

#2
This should help :-

UITableViewCell* cell = (UITableViewCell*)[sender superview];
NSIndexPath* indexPath = [myTableView indexPathForCell:cell];

Here **sender** is the UIButton instance that is sending the event.
**myTableView** is the UITableView instance you're dealing with.

Just get the cell reference right and all the work is done.

You may need to remove the buttons from cell's contentView &
add them directly to UITableViewCell instance as it's subview.

Or

You can formulate a tag naming scheme for different UIButtons in cell.contentView.
Using this tag, later you can know the row & section information as needed.
Reply

#3
Tarun's code doesnt work on iOS7, since the UITableViewCell structure changed and now he would get "UITableViewCellScrollView" instead.

This post

[To see links please register here]

has a good solution creating a loop to find the correct parent view, regardless of any future changes in the structure. It boils down to creating a loop:

UIView *superView = [sender superview];
UIView *foundSuperView = nil;

while (nil != superView && nil == foundSuperView) {
if ([superView isKindOfClass:[UITableViewCell class]]) {
foundSuperView = superView;
} else {
superView = superView.superview;
}
}

The link has code for a more reusable solution, but this should work.
Reply

#4
The reason i like below technique because it also help me to identify the section of table.

Add Button in cell cellForRowAtIndexPath:


UIButton *selectTaskBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[selectTaskBtn setFrame:CGRectMake(15, 5, 30, 30.0)];
[selectTaskBtn setTag:indexPath.section]; //Not required but may find useful if you need only section or row (indexpath.row) as suggested by MR.Tarun
[selectTaskBtn addTarget:self action:@selector(addTask:) forControlEvents:UIControlEventTouchDown];
[cell addsubview: selectTaskBtn];

Event addTask:

-(void)addTask:(UIButton*)btn
{
CGPoint buttonPosition = [btn convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
int currentIndex = indexPath.row;
int tableSection = indexPath.section;
}
}

Hopes this help.
Reply

#5
**Delegates are the way to go.**

As seen with other answers using views might get outdated. Who knows tomorrow there might be another wrapper and may need to use `cell superview]superview]superview]superview]`. And if you use tags you would end up with n number of if else conditions to identify the cell. To avoid all of that set up delegates. _(By doing so you will be creating a re usable cell class. You can use the same cell class as a base class and all you have to do is implement the delegate methods.)_

First we need a interface (protocol) which will be used by cell to communicate(delegate) button clicks. (_You can create a separate .h file for protocol and include in both table view controller and custom cell classes OR just add it in custom cell class which will anyway get included in table view controller_)

@protocol CellDelegate <NSObject>
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data;
@end
Include this protocol in custom cell and table view controller. And make sure table view controller confirms to this protocol.

In custom cell create two properties :

@property (weak, nonatomic) id<CellDelegate>delegate;
@property (assign, nonatomic) NSInteger cellIndex;
In `UIButton` IBAction delegate click : (_Same can be done for any action in custom cell class which needs to be delegated back to view controller_)

- (IBAction)buttonClicked:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(didClickOnCellAtIndex:withData:)]) {
[self.delegate didClickOnCellAtIndex:_cellIndex withData:@"any other cell data/property"];
}
}

In table view controller `cellForRowAtIndexPath` after dequeing the cell, set the above properties.

cell.delegate = self;
cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table.
And implement the delegate in table view controller:

- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data
{
// Do additional actions as required.
NSLog(@"Cell at Index: %d clicked.\n Data received : %@", cellIndex, data);
}

This would be the ideal approach to get custom cell button actions in table view controller.
Reply

#6
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][1] to detect button click in table view for multiple row and section.


[1]:

[To see links please register here]

Reply

#7
Following code might Help you.

I have taken `UITableView` with custom prototype cell class named `UITableViewCell` inside `UIViewController`.

So i have `ViewController.h`, `ViewController.m` and `TableViewCell.h`,`TableViewCell.m`

Here is the code for that:

`ViewController.h`

@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView *tblView;

@end

`ViewController.m`

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return (YourNumberOfRows);
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

static NSString *cellIdentifier = @"cell";

__weak TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

if (indexPath.row==0) {
[cell setDidTapButtonBlock:^(id sender)
{
// Your code here

}];
}
return cell;
}

**Custom cell class :**

TableViewCell.h

@interface TableViewCell : UITableViewCell

@property (copy, nonatomic) void (^didTapButtonBlock)(id sender);

@property (strong, nonatomic) IBOutlet UILabel *lblTitle;
@property (strong, nonatomic) IBOutlet UIButton *btnAction;

- (void)setDidTapButtonBlock:(void (^)(id sender))didTapButtonBlock;

@end

and

UITableViewCell.m

@implementation TableViewCell

- (void)awakeFromNib {
// Initialization code
[self.btnAction addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];

// Configure the view for the selected state
}
- (void)didTapButton:(id)sender {
if (self.didTapButtonBlock)
{
self.didTapButtonBlock(sender);
}
}


**Note**: Here I have taken all `UIControls` using Storyboard.

Hope that can help you...!!!
Reply

#8
@Mani answer is good, however tags of views inside cell's contentView often are used for other purposes. You can use cell's tag instead (or cell's contentView tag):

1) In your `cellForRowAtIndexPath:` method, assign cell's tag as index:

cell.tag = indexPath.row; // or cell.contentView.tag...

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

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

3) Create method that returns row of the sender (thanks @Stenio Ferreira):

- (NSInteger)rowOfSender:(id)sender
{
UIView *superView = sender.superview;
while (superView) {
if ([superView isKindOfClass:[UITableViewCell class]])
break;
else
superView = superView.superview;
}

return superView.tag;
}


4) Code actions based on index:

-(void)yourButtonClicked:(UIButton*)sender
{
NSInteger index = [self rowOfSender:sender];
// Your code here
}
Reply

#9
# Swift 2.2
You need to add target for that button.

myButton.addTarget(self, action: #selector(ClassName.FunctionName(_:), forControlEvents: .TouchUpInside)
**FunctionName: connected** // for example

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:

func connected(sender: UIButton) {
let buttonTag = sender.tag
// Do any additional setup
}
Reply

#10
Instead of playing with tags, I took different approach. Made delegate for my subclass of UITableViewCell(OptionButtonsCell) and added an indexPath var. From my button in storyboard I connected @IBAction to the OptionButtonsCell and there I send delegate method with the right indexPath to anyone interested. In cell for index path I set current indexPath and it works :)

Let the code speak for itself:

**Swift 3 Xcode 8**

**OptionButtonsTableViewCell.swift**

import UIKit
protocol OptionButtonsDelegate{
func closeFriendsTapped(at index:IndexPath)
}
class OptionButtonsTableViewCell: UITableViewCell {
var delegate:OptionButtonsDelegate!
@IBOutlet weak var closeFriendsBtn: UIButton!
var indexPath:IndexPath!
@IBAction func closeFriendsAction(_ sender: UIButton) {
self.delegate?.closeFriendsTapped(at: indexPath)
}
}
**MyTableViewController.swift**

class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, OptionButtonsDelegate {...

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "optionCell") as! OptionButtonsTableViewCell
cell.delegate = self
cell.indexPath = indexPath
return cell
}

func closeFriendsTapped(at index: IndexPath) {
print("button tapped at index:\(index)")
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through