开发者

How can I get the indexPath of UIButton in a customized tableViewCell?

I created a tableViewCell the include an image, two text labels and a uibutton. The button is allocated to an action method (e.g. viewButtonPused:sender).

I'm used to handle开发者_开发百科 row selection with tableView:didSelectRowAtIndexPath: so I could tell which row was selected. But with the uibutton and its action method .... How can I tell?

Thanks in advance.


If the button's target is the UIViewController/UITableViewController or any other object that maintains a reference to the UITableView instance, this will do nicely:

- (void)viewButtonPushed:(id)sender {
    UIButton *button = (UIButton *)sender;
    UITableViewCell *cell = button.superview; // adjust according to your UITableViewCell-subclass' view hierarchy
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    // use your NSIndexPath here
}

Using this approach will let you avoid extra instance variables and will work fine in case you have multiple sections. You need to have a way to access the UITableView instance though.

Edit: as someone pointed out in the comments below, this approach broke in iOS 7. If you're still interested in using this approach over tags, be sure to find the UITableViewCell instance correctly, i.e. by looping through the superviews until you find one.


Define a delegate on the class associated with the Cell's prototype.

// MyCell.h

@protocol MyCellDelegate
- (void)buttonTappedOnCell:(MyCell *)cell;
@end

@interface MyCell : UITableViewCell 
@property (nonatomic, weak) id <MyCellDelegate> delegate;
@end

// MyCell.m

@implementation MyCell

- (void)buttonTapped:(id)sender {
        [self.delegate buttonTappedOnCell:self];
    }
}
@end

Now go to the class you want to make the Cell's delegate. This is probably going to be a UITableView subclass. In the cellForRowAtIndexPath method make sure you assign the delegate of the Cell to self. Then implement the method specified in the protocol.

- (void)buttonTappedOnCell:(MyCell *)cell {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    int row = indexPath.row;
}

Or if you would prefer a blocks based approach:

// MyCell.h

typdef void(^CellButtonTappedBlock)(MyCell *cell);

@interface MyCell : UITableViewCell 
@property (nonatomic, copy) CellButtonTappedBlock buttonTappedBlock;
@end

Then in your tableView's dataSource:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyCell *cell = ....
    __weak typeof(self) weakSelf = self;
    [cell setButtonTappedBlock:^(MyCell *cell) {
        NSIndexPath *indexPath = [weakSelf.tableView indexPathForCell:cell];
        // Do stuff with the indexPath
    }];

}


I know this is an old thread but I find this method best as it is free from superView calls (and thus when Apple change the view hierarchy with new os versions it is left unaffected) and doesn't require subclassing or use of cumbersome tags that can get messed up when the cell is reused.

- (void)buttonPressed:(UIButton *)sender {
    CGPoint location = [sender convertPoint:sender.center toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
    NSLog(@"%@", indexPath);
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   ...
   [cell.customCellButton addTarget:self action:@selector(customCellButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
   [cell.customCellButton setTag:indexPath.row];
}

- (void)customCellButtonTapped:(id)sender {
   UIButton *button = (UIButton *)sender;
   NSLog(@"indexPath.row: %d", button.tag);
}


If you have directly added elements on the cell itself (which you shouldnt) -

NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[sender superview] ];

If you have added elements on the contentView of the cell (which is the proposed way)

NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview] ];


define one class variable int SelectedRow; inside didSelectRowAtIndexPath assign value to it like SelectedRow = indexPath.row;

use this SelectedRow variable in side your action method viewButtonPused:sender


Instead of adding the button as a subview of the cell set it to be cell.accessoryView. Then use tableView:accessoryButtonTappedForRowWithIndexPath: to do your stuff that should be done when a user taps this button.


Another way that I use now is to subclass UIButton and add a property of type NSIndexPath. On cellForRowAtIndexPath I assign the value of indexPath and its available at the action method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜