22

我有一个表格视图,其中每个单元格都有一个按钮附件视图。该表由获取的结果控制器管理,并经常重新排序。我希望能够按下其中一个按钮并获得该按钮的表格视图单元格的索引路径。几天来,我一直试图通过将按钮的行存储在其标签中来使其正常工作,但是当表格重新排序时,该行变得不正确,并且我一直无法正确重新排序标签。关于如何跟踪按钮单元格的索引路径的任何新想法?

4

8 回答 8

31

如果您对依赖 感到不舒服button.superview,则此方法应该比此处的其他一些答案更强大:

UIButton *button = (UIButton *)sender;
CGRect buttonFrame = [button convertRect:button.bounds toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonFrame.origin];
于 2013-01-08T01:14:11.497 回答
25

这停止在 iOS 7 上工作;改为查看Mike Weller 的答案

- (IBAction)clickedButton:(id)sender {
    UIButton *button = (UIButton *)sender;
    UITableViewCell *cell = (UITableViewCell *)button.superview;
    UITableView *tableView = (UITableView *)cell.superview;
    NSIndexPath *indexPath = [tableView indexPathForCell:cell];
}

或更短:

- (IBAction)clickedButton:(id)sender {
    NSIndexPath *indexPath = [(UITableView *)sender.superview.superview indexPathForCell:(UITableViewCell *)sender.superview];
}

两者都未经测试!

于 2010-05-19T08:46:55.450 回答
21

用(就像所有现有答案所展示的那样)爬取视图层次结构.superview是一种非常糟糕的做事方式。如果UITableViewCell的结构发生变化(以前发生过),您的应用程序将中断。看到.superview.superview你的代码应该会敲响警钟。

按钮及其处理程序应添加到自定义UITableViewCell子类并在那里布局。那就是它的归属。

然后,单元子类可以通过标准委托接口或块委托按钮事件。你应该瞄准这样的事情:

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyCustomCell *cell = ...;

    // ...

    cell.onButtonTapped = ^{
        [self buttonSelectedAtIndexPath:indexPath];
    }

    // OR

    cell.delegate = self;

    // ...
}

(注意:如果你走块路线,你将需要使用__weak自引用来防止保留循环,但我认为这会使示例混乱)。

如果您采用委托路线,那么您将拥有此委托方法来实现:

- (void)cellButtonPressed:(UITableViewCell *)cell
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    // ...
}

现在,您的代码在处理事件时可以完全访问相应的上下文。

在你的单元类上实现这个接口应该很简单。

于 2013-04-10T10:11:23.357 回答
9

不知道为什么需要调用superview方法两次才能得到UITableViewCell。

更新:

感谢秋朗,现在明白了。

“那是因为 SDK 现在为 UITableViewCell 添加了一个名为 UITableViewCellContentView 的私有类,它现在是按钮的超级视图。” ——秋朗

UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
UITableView *curTableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [curTableView indexPathForCell:cell];
于 2012-07-18T15:51:34.793 回答
6

我也遇到了同样的问题,并构建了一个简单的递归方法,无论您触发控制的深度有多少,该方法都有效。

-(NSIndexPath*)GetIndexPathFromSender:(id)sender{

    if(!sender) { return nil; }

    if([sender isKindOfClass:[UITableViewCell class]])
    {
        UITableViewCell *cell = sender;
        return [self.tableView indexPathForCell:cell];
    }

    return [self GetIndexPathFromSender:((UIView*)[sender superview])];
}


-(void)ButtonClicked:(id)sender{
    NSIndexPath *indexPath = [self GetIndexPathFromSender:sender];
}
于 2013-09-25T19:33:39.687 回答
4

我创建了一种获取 indexPath 的方法,希望对您有所帮助。

在 cellForRowAtIndexPath 中创建按钮操作 (aMethod:)

-(void) aMethod:(UIButton *)sender
{
    // Calling Magic Method which will return us indexPath.
    NSIndexPath *indexPath = [self getButtonIndexPath:sender];

    NSLog(@"IndexPath: %li", indexPath.row);
    NSLog(@"IndexRow: %li", indexPath.section);
}

// 这里是获取按钮 indexPath 的魔术方法

-(NSIndexPath *) getButtonIndexPath:(UIButton *) button
{
    CGRect buttonFrame = [button convertRect:button.bounds toView:groupTable];
    return [groupTable indexPathForRowAtPoint:buttonFrame.origin];
}
于 2015-03-11T16:13:53.847 回答
3

使用这个完美的为我工作。

CGPoint center= [sender center];
CGPoint rootViewPoint = [[sender superview] convertPoint:center toView:_tableView1];
NSIndexPath *indexPath = [_tableView1 indexPathForRowAtPoint:rootViewPoint];
NSLog(@"%@",indexPath);
于 2014-11-21T08:12:55.860 回答
2

斯威夫特 2 更新

以下是如何找出点击了哪个按钮

 @IBAction func yourButton(sender: AnyObject) {


 var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let indexPath = self.tableView.indexPathForRowAtPoint(position)
    let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
    UITableViewCell
    print(indexPath?.row)
    print("Tap tap tap tap")

}
于 2015-11-07T21:21:06.287 回答