Objective c - Best practice to handle a button touch event for a button of a custom UITableViewCell
ios, objective-c, uibutton, uitableview
Solution
Store the row of the cell as `tag` property of your custom button.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// bla bla bla
if (!cell)
{
//bla bla bla
[cell.yourButton addTarget:self selector:@selector(yourButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
// bla bla bla
cell.yourButton.tag = indexPath.row;
}
-(void)yourButtonTapped:(id)sender
{
int tag = [(UIButton *)sender tag];
NSLog(@"tapped button in cell at row %i", tag);
}
Problem
What is best practice to handle a button touch event for a button of a custom `UITableViewCell`? my classes: `MyViewController`, `MyCustomCell` I can think of three options: First option- Have the button as a property of `MyCustomCell`, and then add a target to it in the `MyViewController` .m file with `MyViewController` as the target. `MyViewController` .m file ``` - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"customCell"; MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; [cell.theButton addTarget:self action:@selector(theButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; } // Configure the cell... [self configureCell:cell atIndexPath:indexPath]; return cell; } - (void)theButtonTapped:(UIButton *)sender { MyCustomCell *selectedCell = (MyCustomCell *)sender.superview; if (selectedCell) { NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell]; MyModel *selectedModel = [self.model objectAtIndex:indexPath.row]; // do something with the model... } } ``` Second option- If the custom cell was made in IB, Set the nib File's Owner to be `MyViewController`, implement `buttonTapped:` method in `MyViewController` and connect the button's Touch Up Inside event to the `buttonTapped:` method. Third option- if the custom cell wasn't made in IB, add a target to the button in the `MyCustomCell` .m file with `MyCustomCell` as the target. Define a `MyCustomCellDelegate` add `@property (nonatomic, assign) id<MyCustomCellDelegate> delegate` to `MyCustomCell` and call this delegate when button tapped. Set `MyViewController` as the cell's delegate when creating cells and implement the `MyCustomCellDelegate` protocol. `MyCustomCell` .h file ``` @class MyCustomCell; @protocol MyCustomCellDelegate <NSObject> - (void)buttonTappedOnCell:(MyCustomCell *)cell; @end @interface MyCustomCell : UITableViewCell @property (nonatomic, retain) UIButton *theButton; @property (nonatomic, assign) id<MyCustomCellDelegate> delegate; @end ``` `MyCustomCell` .m file ``` - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Initialization code self.theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.theButton.frame = CGRectMake(10,10,50,30); [self addSubview:self.theButton]; [self.theButton addTarget:self action:@selector(theButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; } return self; } - (void)theButtonTapped:(UIButton *)sender { [self.delegate buttonTappedOnCell:self]; } ``` `MyViewController` .m file ``` - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"customCell"; MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; cell.delegate = self; } // Configure the cell... [self configureCell:cell atIndexPath:indexPath]; return cell; } - (void)buttonTappedOnCell:(MyCustomCell *)selectedCell { if (selectedCell) { NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell]; MyModel *selectedModel = [self.model objectAtIndex:indexPath.row]; // do something with the model... } } ```