【问题标题】:How can I keep track of the index path of a button in a table view cell?如何跟踪表格视图单元格中按钮的索引路径?
【发布时间】:2011-02-21 06:41:42
【问题描述】:

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

【问题讨论】:

标签: iphone cocoa-touch uitableview nsindexpath


【解决方案1】:

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

}

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        这在 iOS 7 中停止工作;改为查看Mike Weller's answer

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

        两者都未经测试!

        【讨论】:

        • 非常感谢!这解决了问题,现在我终于可以继续了 :) 对于那些稍后到达这里并想要实现它的人,在第一个示例中,您需要少调用一次 superview 调用来获取 UITableViewCell 并且 superview 都是小写的。否则,一切都是完美的(我没有尝试过更短的例子)。
        • 你是对的,编辑了我的答案 ;) 我在 2 .superviews 背后的逻辑以获得 UITableViewCell:单元格是 accessoryView 的 superview,即 @987654328 @ 的UIButton。但我想我错了。
        • 这可能有效,但至少可以说爬上视图层次结构是一种“气味”。如果UITableViewCell 的视图结构发生变化,您的应用程序就会中断。这在过去发生过。按钮及其处理程序应存在于自定义单元子类中。然后这个单元类可以提供一个委托或块回调接口,以便您的视图控制器可以以这种方式挂钩到按钮事件并具有对适当上下文的完全访问权限。
        • 详情请看我的回答。
        • @MikeWeller Smell 已确认。这在 iOS7 中中断。 cell.superView 现在返回 UITableViewWrapperView 而不是 tableView 本身。
        【解决方案5】:

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

        【讨论】:

        • 那是因为SDK现在为UITableViewCell添加了一个私有类UITableViewCellContentView,现在是button的superview。
        【解决方案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];
        }
        

        【讨论】:

        • 小心无限递归...为了安全起见,我可能会在该方法的顶部添加一个逃生舱口:if(!sender) { return nil; }
        • 这个 getIndexPathFromSender 方法是 Grrrrrreat!
        【解决方案7】:

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

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

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

        【讨论】:

          【解决方案8】:

          如果您对依赖button.superview 感到不自在,则此方法应该比此处的其他一些答案更可靠:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多