如何跟踪表视图单元格中按钮的索引路径?

发布于 2024-09-01 22:56:06 字数 176 浏览 11 评论 0原文

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

I have a table view where each cell has a button accessory view. The table is managed by a fetched results controller and is frequently reordered. I want to be able to press one of the buttons and obtain the index path of that button's table view cell. I've been trying to get this working for days by storing the row of the button in its tag, but when the table gets reordered, the row becomes incorrect and I keep failing at reordering the tags correctly. Any new ideas on how to keep track of the button's cell's index path?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

甚是思念 2024-09-08 22:56:07

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

UIButton *button = (UIButton *)sender;
CGRect buttonFrame = [button convertRect:button.bounds toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonFrame.origin];

If you feel uncomfortable relying on button.superview, this method should be a little more robust than some of the other answers here:

UIButton *button = (UIButton *)sender;
CGRect buttonFrame = [button convertRect:button.bounds toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonFrame.origin];
青芜 2024-09-08 22:56:07

这不再适用于 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];
}

两者都未经测试!

This stopped working with iOS 7; check out Mike Weller's answer instead

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

Or shorter:

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

Both are untested!

z祗昰~ 2024-09-08 22:56:07

使用 .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];
    // ...
}

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

在您的单元类上实现此接口应该很简单。

Crawling up view hierarchies with .superview (like all of the existing answers demonstrate) is a really bad way to do things. If UITableViewCell's structure changes (which has happened before) your app will break. Seeing .superview.superview in your code should set off alarm bells.

The button and its handler should be added to a custom UITableViewCell subclass and layed out there. That's where it belongs.

The cell subclass can then delegate out the button event through a standard delegate interface, or a block. You should aim for something like this:

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

    // ...

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

    // OR

    cell.delegate = self;

    // ...
}

(Note: if you go the block route, you will need to use a __weak self reference to prevent retain cycles, but I thought that would clutter up the example).

If you take the delegate route you would then have this delegate method to implement:

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

Your code now has full access to the appropriate context when it handles the event.

Implementing this interface on your cell class should be straightforward.

酸甜透明夹心 2024-09-08 22:56:07

我不知道为什么我需要调用方法 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];

I don't know why I need to call the method superview twice to get the UITableViewCell.

Update:

Thank for Qiulang, now I got it.

"That's because SDK now has added a private class called UITableViewCellContentView for UITableViewCell, which is button's superview now." – Qiulang

UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
UITableView *curTableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [curTableView indexPathForCell:cell];
老娘不死你永远是小三 2024-09-08 22:56:07

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

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

I had this same issue also and built a simple recursive method that works no matter how many views deep you triggering control is.

-(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];
}
何必那么矫情 2024-09-08 22:56:07

我创建了一种获取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);
}

// 这是获取按钮索引路径的魔术方法

-(NSIndexPath *) getButtonIndexPath:(UIButton *) button
{
    CGRect buttonFrame = [button convertRect:button.bounds toView:groupTable];
    return [groupTable indexPathForRowAtPoint:buttonFrame.origin];
}

I have created one Method for getting indexPath, Hope this will help you.

Create Button Action (aMethod:) in cellForRowAtIndexPath

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

// Here is the Magic Method for getting button's indexPath

-(NSIndexPath *) getButtonIndexPath:(UIButton *) button
{
    CGRect buttonFrame = [button convertRect:button.bounds toView:groupTable];
    return [groupTable indexPathForRowAtPoint:buttonFrame.origin];
}
如此安好 2024-09-08 22:56:07

使用这个完美为我工作。

CGPoint center= [sender center];
CGPoint rootViewPoint = [[sender superview] convertPoint:center toView:_tableView1];
NSIndexPath *indexPath = [_tableView1 indexPathForRowAtPoint:rootViewPoint];
NSLog(@"%@",indexPath);

Use this Perfect working for me.

CGPoint center= [sender center];
CGPoint rootViewPoint = [[sender superview] convertPoint:center toView:_tableView1];
NSIndexPath *indexPath = [_tableView1 indexPathForRowAtPoint:rootViewPoint];
NSLog(@"%@",indexPath);
过度放纵 2024-09-08 22:56:07

SWIFT 2 UPDATE

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

 @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")

}

SWIFT 2 UPDATE

Here's how to find out which button was tapped

 @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")

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文