Custom button in UITableViewCell – indexPath
Hi all
I am currently working on iPhone app number two when I came across a problem that it has taken me a while to sort out. Â I wanted to place a button inside each UITableCell I am displaying. Â I then wanted to call a method when the user pressed that button which would perform some action on the information related to the contents of that cell.
For this to be useful I needed to be able to get the indexpath of the row in which the button was pressed. Â It took me a while to work this out but I eventually came up with a solution which is really simple, in fact so simple I am angry I did not work it out sooner. Below is the line of code I am using in my button method to get the indexPath.
The method signature used was:
From this point on I was then able to access the section and row of the cell in which the button was pressed using:
NSInteger row = indexPath.row;
Mike
28 Comments
mike on December 16th, 2008
Thanks for your reply Rajeev.
I am using the code I have provided above within my app and its working fine. I think that [sender superview] will give me the contentView within the cell rather than the cell itself, that is why I am using [[sender superview] superview]. The first superview being the contentView of the cell and the second superview being the cell itself.
If this was giving me the tableView then my app would not be working.
Happy to take more comments on this.
Thanks
Mike
Harsha on December 24th, 2008
I thank u both a lot…i too needed this information…thanks a lot….[:)]
mike on December 24th, 2008
Thanks Harsha, happy to help. If you have any questions you like to share feel free to do so. I’ve been working through all sorts recently and I’d be happy to answer any other questions if I can.
Happy Christmas
Mike
Tom on December 25th, 2008
Mike,
This is timely for me as well. I’ve tried both versions above but I always get a row of 0 when I run this regardless of which row I click.
Any ideas?
Thanks,
Tom
mike on December 27th, 2008
Hi Tom
Are you able to post the code you are using. I am not sure why you are getting a row back or 0 at the moment. If I can see the methods it may help and I’d be happy to take a look.
Mike
collin on January 15th, 2009
Thanks, you saved me a lot of headache. This was the first thing that came up on my google search!
Leachy Peachy on January 17th, 2009
You rock. I was wondering what I was doing wrong. Thanks for the help.
IrvTheSwirv on February 3rd, 2009
You’ve just saved me a WHOLE load of digging. Cheers for that!
Benno on February 27th, 2009
Wow! I tried TONS of different ways to get buttons on each row working but to no avail until i found this. I had the same kind of “I can’t believe I didn’t think of this already!” moment as soon as i saw the crucial line: [[sender superview] superview]
I love the iPhone and i love making apps for it, but it’s horrible hacks like this that make me cry myself to sleep at night.
Thanks so much for your insight though, this programmer will sleep well tonight =D
Joe on March 18th, 2009
While this works, it is not a good practice. Especially when you have an even deeper view hierarchy in a UITableViewCell or if UITableViewCell’s implementation ever changes (don’t think Apple hasn’t done it before).
The better option is to set the tag of your UIButton to the row that its UITableViewCell is being shown at. You can set the target/action when you create a cell, and set a tag every time you return a cell. In your action method, you can just grab the [sender tag] to get the row the button is in.
Anonymous on March 19th, 2009
@Joe, thanks for the info. I’m sure I tried doing it with the tag and for some reason was not able to do what I needed, but your point on deeper hierarchies or the implementation changing is valid and so I’ll have to try again using Tag and see how I get on.
Cheers
Mike
Anonymous on March 19th, 2009
I’ve just remembered the problem I came across, although I think now I would be able to solve it, but back when I had the problem I wanted to get to both the section and the row as the rows could be in different sections. I could just put the row and section into a string in the button Tag with some kind of delimiter and then explode it later, but at the time I found the superview approach first and it worked.
If Apple ever did change the implementation it would come with a new SDK and some work would be required to change how this worked, but for my needs I think I’ll stick with this rather than exploding strings etc.
Mike
Joe on March 19th, 2009
Here you go: http://weblog.bignerdranch.com/?p=56
And if you using multiple sections, I would be surprised if the buttons in each section didn’t have a different action. In this approach, that works out, because you know which action messages are being sent from which section simply by what they are trying to do. Of course, another approach would be to [button setTag:[indexPath section] * 1000 + [indexPath row], and then you can divide by 1000 to get the section and your row is the remainder. :)
links for 2009-07-03 | manicwave.com on July 3rd, 2009
[...] 71² » Custom button in UITableViewCell – indexPath NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]]; (tags: iphone uitableview) [...]
Anonymous on July 21st, 2009
awesome – you saved me :)
Thanks a million!
Mubashir
Ross Nelson on October 24th, 2009
I spent HOURS trying to get this to work trying everything I could think of until I ran across this post. Works perfectly. Thanks!
Anonymous on October 30th, 2009
Thanks a million! Still helping people after almost a year, good work.
Anonymous on December 23rd, 2009
SIMPLY AMAZING!!
I wish I’d found this five hours ago!! ;)
mike on December 23rd, 2009
LOL, If I had a penny for the number of times I’ve said the same thing on finding a nugget on the net I’d have fewer wrinkles :o)
Glad it helped you out
Mike
JOnSok on January 30th, 2010
HI I used your example and got the following build error
error: request for member ‘tableView’ in something not a structure or union
any ideas, its driving me crazy
Giova on February 24th, 2010
GREAAAAT!!!!!!! Thank you man, Awesome and super useful post, really, I’ve browsed so many blogs before findind you!!
Thanks
Andiih on April 1st, 2010
Yep. still useful!
Rob on April 20th, 2010
Hi Mike,
Thanks for the awesome tip!
I’m trying to do the same thing, but I’m getting an error in my TableViewCell subclass for the “NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];” saying that the “Request for member ‘tableView’ in something that is not a structure or union”.
Do I need to pass that down somehow?
Thanks again for getting me one step closer!!
Rob P on May 8th, 2010
You rock man… super simple and easy to implement!
@Rob above, make sure it is within a uitableviewcontroller and you have setup the dataSource and delegate. The code should be something like this within the parent view controller for that table:
- (void)buttonMethod:(UIButton *)sender {
// method for finding what button was pressed
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
NSLog(@”Button is in section %d and row %d”, section, row);
}
and then put this in the .h file
UIButton *buttonMethod;
and
- (void)buttonMethod:(UIButton *)sender;




Rajeev on December 15th, 2008
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
please change this statement to
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[sender superview]];
with this you will get the index path for the cell. But with your previous statement you were getting the table view not the cell index path.