Getting a UITableView cell row when a button is clicked

I have a table controller that displays a row of cells. Each cell has 3 buttons. I numbered tags for each cell equal to 1,2,3. The problem is that I don’t know how to find which cell the button is clicked on. Currently, I only get the sender tag when one of the buttons was pressed. Is there a way to get the row number of a cell when a button is pressed?

+84
ios objective-c uitableview
Sep 21 '11 at 18:00
source share
10 answers

Instead, you should use this method:

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition]; 

Quick version:

 let buttonPosition = sender.convert(CGPoint(), to:tableView) let indexPath = tableView.indexPathForRow(at:buttonPosition) 

This will give you indexPath depending on the position of the button that was pressed. Then you just call cellForRowAtIndexPath if you need a cell or indexPath.row if you need a row number.

If you are paranoid, you can check if (indexPath) ... before using it, only if indexPath not found for this point in the table view.

All other answers may break if Apple decides to change the presentation structure.

+275
Apr 29 '13 at 1:58
source share

Edit: This answer is deprecated. Use this method instead




Try the following:

 -(void)button1Tapped:(id)sender { UIButton *senderButton = (UIButton *)sender; UITableViewCell *buttonCell = (UITableViewCell *)[senderButton superview]; UITableView* table = (UITableView *)[buttonCell superview]; NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell]; NSInteger rowOfTheCell = [pathOfTheCell row]; NSLog(@"rowofthecell %d", rowOfTheCell); } 

Edit: if you use contentView, use buttonCell instead:

 UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview; 
+40
Sep 21 '11 at 18:48
source share

I would recommend this way to get the index cell of a cell that has any custom view - ( compatible with iOS 7, as well as with all previous versions )

 -(void)button1Tapped:(id)sender { //- (void)cellSubviewTapped:(UIGestureRecognizer *)gestureRecognizer { // UIView *parentCell = gestureRecognizer.view.superview; UIView *parentCell = sender.superview; while (![parentCell isKindOfClass:[UITableViewCell class]]) { // iOS 7 onwards the table cell hierachy has changed. parentCell = parentCell.superview; } UIView *parentView = parentCell.superview; while (![parentView isKindOfClass:[UITableView class]]) { // iOS 7 onwards the table cell hierachy has changed. parentView = parentView.superview; } UITableView *tableView = (UITableView *)parentView; NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)parentCell]; NSLog(@"indexPath = %@", indexPath); } 

This does not require self.tablview .

Also, pay attention to the commented code, which is useful if you want it to be added to your custom view using @selector of the UIGestureRecognizer user.

+17
Oct 18 '13 at 3:20
source share

There are two ways:

  • @ H2CO3 is correct. You can do what @ user523234 suggested, but with a slight change, respect the UITableViewCellContentView, which should be between UIButton and UITableViewCell. Therefore, to change its code:

     - (IBAction)button1Tapped:(id)sender { UIButton *senderButton = (UIButton *)sender; UITableViewCellContentView *cellContentView = (UITableViewCellContentView *)senderButton.superview; UITableViewCell *tableViewCell = (UITableViewCell *)cellContentView.superview; UITableView* tableView = (UITableView *)tableViewCell.superview; NSIndexPath* pathOfTheCell = [tableView indexPathForCell:tableViewCell]; NSInteger rowOfTheCell = pathOfTheCell.row; NSLog(@"rowofthecell %d", rowOfTheCell); } 
  • If you create a custom UITableViewCell (your own subclass), you can just call self in IBAction. You can associate the IBAction function with your button using a storyboard or programmatically when you set up a cell.

     - (IBAction)button1Tapped:(id)sender { UITableView* tableView = (UITableView *)self.superview; NSIndexPath* pathOfTheCell = [tableView indexPathForCell:self]; NSInteger rowOfTheCell = pathOfTheCell.row; NSLog(@"rowofthecell %d", rowOfTheCell); } 
+3
Sep 17 '12 at 22:34
source share

I assume that you add buttons to a cell in cellForRowAtIndexPath , then I would do to create a custom subclass of UIButton , add a tag called rowNumber , and add this data until you add a button to the cell.

+2
Sep 21 '11 at 18:04
source share

Another easy way:

  • Get the sense of touch in tableView

  • Then enter the index path of the cell at

  • The index path contains the row index

The code:

 - (void)buttonTapped:(id)sender { UITapGestureRecognizer *tap = (UITapGestureRecognizer *)sender; CGPoint point = [tap locationInView:theTableView]; NSIndexPath *theIndexPath = [theTableView indexPathForRowAtPoint:point]; NSInteger theRowIndex = theIndexPath.row; // do your stuff here // ... } 
+2
Mar 31 '14 at 1:22
source share

Swift 3

Note. This should really go in the accepted answer above, except that the meta frowns at such changes.

 @IBAction func doSomething(_ sender: UIButton) { let buttonPosition = sender.convert(CGPoint(), to: tableView) let index = tableView.indexPathForRow(at: buttonPosition) } 

Two small comments:

  • The function by default has a sender type like Any, which does not have conversion.
  • CGPointZero can be replaced with CGPoint ()
+1
Mar 16 '17 at 19:07
source share

One solution might be to check the tag for the add-in button or even higher in the hierarchy of views (if the button is in the view of the contents of the cell).

0
Sep 21 '11 at 18:09
source share

I would like to share the code in swift -

 extension UITableView { func indexPathForCellContainingView(view1:UIView?)->NSIndexPath? { var view = view1; while view != nil { if (view?.isKindOfClass(UITableViewCell) == true) { return self.indexPathForCell(view as! UITableViewCell)! } else { view = view?.superview; } } return nil } } 
0
Jul 25 '16 at 14:12
source share

Quickly:

 @IBAction func buttonAction(_ sender: UIButton) { guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else { return } // do something } 
0
Dec 29 '17 at 16:52
source share



All Articles