Two buttons in a UITableViewCell: how to determine which indexPath was selected?

I want to place two buttons in each cell of the table view. When I click on button number one, I want the application to display a warning message: "You pressed button 1 at the pointer: 3.0". My problem: how can I put buttons in a table cell? Can anyone guide me?

+4
source share
2 answers

Taking the @wedo answer and simplifying it a bit - you essentially need two pieces of information: the row number and the column that was used (the β€œcolumn” is the order of the button).


Solution 1 is not a bad decision

This can be saved on the button using button.tag and button.titleLabel.tag . In -tableView:cellForRowAtIndexPath: you will do the following:

 UIButton *button0 = [UIButton buttonWithType:UIButtonTypeCustom]; button0.tag = indexPath.row; button0.titleLabel.tag = 0; // button #0 (or column 0) [button0 addTarget:self action:@selector(cellButtonAction:) forControlEvents:UIControlEventTouchUpInside]; [cell.contentView addSubview:button0]; 

Your cellButtonAction: method will look like this:

 - (IBAction)answerButtonAction:(UIButton *)sender { NSInteger row = sender.tag; NSInteger column = sender.titleLabel.tag; // do something } 

Solution 2 is a much better solution.

The above works and everything is fine, but these are pretty hacks. Alternatively, it may take 3 minutes to subclass the button and add a property that can contain the values ​​of rows and columns.

 @interface IndexPathButton: UIButton // NSIndexPath provides a convenient way to store an integer pair // Note we are using cellIndex.section to store the column (or button #) @property (strong, nonatomic) NSIndexPath *cellIndex; @end @implementation IndexPathButton @end 

You would use this in the same way as the previous solution, but save the values ​​in a custom property, not in tags. In tableView:cellForRowAtIndexPath:

 // You'd create a button for each column here IndexPathButton *button0 = [IndexPathButton buttonWithType:UIButtonTypeCustom]; button0.indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:0]; [button0 addTarget:self action:@selector(cellButtonAction:) forControlEvents:UIControlEventTouchUpInside]; [cell.contentView addSubview:button0]; 

Solution 3 is the best solution.

UITableViewCells should typically use delegation for any heavy lifting that needs to be done. This pattern most closely matches the Apple delegation pattern for cells, for example. tableView:didSelectRowAtIndexPath and friends. So, let me create a base class, tableViewCell, which can be used to handle any number of controls and which should not go around indexPaths.

 /** Simple protocol to allow a cell to fire any type of action from a control. */ @protocol SOTableViewCellActionDelegate <NSObject> @required -(void)tableViewCell:(UITableViewCell *)cell didFireActionForSender:(id)sender; @end @interface SOActionCell : UITableViewCell @property (nonatomic, weak) id<SOTableViewCellActionDelegate> delegate; @end @implementation SOActionCell -(void)fireAction:(id)sender { [self.delegate tableViewCell:self didFireActionForSender:sender]; } @end 

In -tableView:cellForRowAtIndexPath: you will do the following:

 UIButton *button0 = [UIButton buttonWithType:UIButtonTypeCustom]; button0.tag = 0; [button0 addTarget:cell action:@selector(fireAction:) forControlEvents:UIControlEventTouchUpInside]; [cell.contentView addSubview:button0]; 

Then we implement the required delegate method in tableViewController:

 -(void)tableViewCell:(UITableViewCell *)cell didFireActionForSender:(id)sender { NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; NSAssert(indexPath, @"indexPath of cell shall always be found."]; if (!indexPath) return; // do whatever you want to do with your button action here // using indexPath, sender tag, button title, etc. } 
+7
source

Using indexPath as the value of an OK tag when you have only one button in a UITableCell, but if you want to track more, you can use the modulo operator:

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath { ... imageButton1.tag=indexPath.row*2; [imageButton1 addTarget:self action:@selector(buttonPushed:) [cell.contentView addSubview:imageButton]; ... imageButton2.tag=indexPath.row*2+1; [imageButton2 addTarget:self action:@selector(buttonPushed:) [cell.contentView addSubview:imageButton]; 

for the selector, you can distinguish between buttons and get indexPath as follows:

 -(void) buttonPushed:(id)sender{ UIButton *button = (UIButton *)sender; switch (button.tag%2) { case 0: // imageButton1 is pressed // to reach indexPath of the cell where the button exists you can use: // ((button.tag-button.tag%2)/2) break; case 1: // imageButton2 is pressed break; } 

An example for 2 buttons, but you can configure it according to the number of buttons.

+5
source

Source: https://habr.com/ru/post/1336008/


All Articles