按下按钮获取UITableView单元格的行


84

我有一个显示一行单元格的tableview控制器。每个单元都有3个按钮。我已将每个单元格的标签编号为1,2,3。问题是我不知道如何找到在哪个单元格上按下了按钮。我目前仅在按下其中一个按钮时才得到发件人的标签。当按下按钮时,是否还有办法获取单元格的行号?

Answers:


278

您实际上应该使用此方法:

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

迅捷版:

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

这将为您indexPath提供所按按钮的位置。然后,cellForRowAtIndexPath如果需要此单元格或indexPath.row需要行号,则只需致电。

如果您偏执狂,可以if (indexPath) ...在使用前进行检查,以防万一indexPath在表视图上找不到该点。

如果Apple决定更改视图结构,则所有其他答案都可能无效。


8
一百万次 没有一个其他的工作,但这是完美的,到目前为止是最简单的解决方案
ine13年

2
该答案有效,因为它是正确的解决方案。其他是解决方法。谢谢!
布鲁诺·菲利普

1
如果你具备self.tableview,请参阅我的回答此页面上。
Ashok

1
一旦我意识到发件人是错误的班级,这对我就起作用了。修复了按下UIButton的问题,现在可以正常工作了!
lordB8r 2014年

1
只是记住方法convertPoint:*to*View不是convertPoint:*from*View。我使用了Xcode自动完成功能,最终使用fromView方法导致无法正常工作...
tGilani

40

编辑:这个答案已经过时。 请改用此方法


试试这个:

-(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);
}

编辑:如果您使用的是contentView,请改为将其用于buttonCell:

UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview;

1
您不应该向单元格本身添加子视图,而只能向其contentView属性添加子视图-因此此解决方案实际上并不起作用。

1
我同意@ H2CO3,而且我也不认为应该通过引用超级视图来完成。请在下面查看更好的方法:stackoverflow.com/a/16270198/308315
iwasrobbed 2013年

@minimalpop您能否更改正确答案?有更好的Q / A!
Thomas Besnehard 2014年

这在iOS 7中不起作用。使用indexPathForRowAtPoint:在下面回答
Austin

我用UICollectionView尝试了相同的版本,并且运行良好。非常感谢!
克劳斯

18

我建议使用这种方式来获取具有任何自定义子视图的单元格的indexPath-(与iOS 7以及所有以前的版本兼容

-(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);
}

这都不要求self.tablview

另外,请注意注释的代码,如果希望通过添加到自定义子视图中的UIGestureRecognizer的@selector进行相同操作,这将很有用。


如果我需要在uitableviewcontroller中找到数据怎么办?
iosMentalist

好的答案。如果您有搜索栏,并且想知道当前使用的是哪个表,则也可以使用它。
Suraj K Thomas

表单元的层次结构已更改?您可以帮助我了解发生了什么变化,并且可以进一步变化吗?
Kamaldeep singh Bhatia

3

有两种方法:

  1. @ H2CO3是正确的。您可以执行@ user523234建议的操作,但有一点点更改,以尊重应该放在UIButton和UITableViewCell之间的UITableViewCellContentView。因此,修改他的代码:

    - (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);
    }
    
  2. 如果创建自定义UITableViewCell(您自己的子类),则只需self在IBAction中进行调用。您可以通过使用情节提要或在设置单元时以编程方式将IBAction功能链接到按钮。

    - (IBAction)button1Tapped:(id)sender
    {
        UITableView* tableView = (UITableView *)self.superview;
        NSIndexPath* pathOfTheCell = [tableView indexPathForCell:self];
        NSInteger rowOfTheCell = pathOfTheCell.row;
        NSLog(@"rowofthecell %d", rowOfTheCell);
    }
    

2

我假设您向中的单元格添加了按钮cellForRowAtIndexPath,那么我要做的就是创建一个自定义类子类UIButton,添加一个名为的标记rowNumber,并在将按钮添加至单元格时追加该数据。


3
很好,但是没有理由为其创建子类UIButtontag是的共同属性UIView
罗布·纳皮尔

不知道我在想什么,并假设用户界面不是用户界面,感谢您的纠正!
Derek Li

2

另一个简单的方法:

  • 在tableView中取得联系

  • 然后获取该点的单元格索引路径

  • 索引路径包含行索引

代码是:

- (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
    // ...
}

1

迅捷3

注意:这确实应该在上面接受的答案中,但meta对此类编辑不满意。

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

两个小意见:

  1. 默认函数的发件人类型为Any,没有转换。
  2. CGPointZero可以替换为CGPoint()

完美运作。

0

一种解决方案是检查按钮的超级视图的标签,甚至检查视图层次结构中的标签(如果按钮位于单元格的内容视图中)。


0

我想快速共享代码-

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

迅速:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.