【问题标题】:indexPathForRowAtPoint returns nil only for first cell in a uitableviewindexPathForRowAtPoint 仅对 uitableview 中的第一个单元格返回 nil
【发布时间】:2014-04-17 14:11:25
【问题描述】:

我在自定义UITableViewCell 中有一个UIButton,它在按下按钮时会删除单元格。为了获取按钮所在单元格的 indexPath,我在按下按钮时调用的方法中调用indexPathForRowAtPoint:,如下所示:

-(void)buttonPressed:(UIButton *)sender{
    CGPoint btnPosition = [sender convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:btnPosition];

    if (indexPath != nil)
    {
    //remove the cell from the tableview. 
    }
}

如果我在除第一个单元格之外的任何单元格中按下按钮,并且在表格中只有一个单元格时,这都可以正常工作。但是,如果有多个单元格并且我在第一个单元格中按下按钮,则触发按钮按下并找到 btnPosition,但[self.tableView indexPathForRowAtPoint:btnPosition]; 返回nil

例如,如果有三个单元格,每个单元格都有一个按钮:

  1. 我按下第一个单元格按钮:buttonPressed 被调用,但 indexPath 为 nil,所以什么也没有发生。
  2. 我按下第三个单元格按钮:buttonPressed 被调用,并且单元格被按预期删除。
  3. 我再次按下第一个单元格:和以前一样,调用 buttonPressed 但 indexPath 为 nil。
  4. 我按下了第二个单元格按钮:buttonPressed 被调用并且单元格被按预期删除。
  5. 我按下了第一个单元格按钮:这一次,buttonPressed 被调用,indexPath 不是 nil 并且单元格被按预期删除。

我已经检查了 tableView 不为零,正如相关但不同的帖子所建议的那样。我还确认btnPosition 点在[self.tableView indexPathForRowAtPoint:btnPosition] == nil[self.tableView indexPathForRowAtPoint:btnPosition] != nil 时都设置为相同的值(x=260, y=44.009995)

所以除了询问是否有人对这里可能发生的事情有任何想法之外,我的问题是:

在什么情况下将相同的 CGPoint 传递给 [self.tableView indexPathForRowAtPoint:btnPosition] 会返回不同的(或零)indexPath

如果有任何想法可以帮助我查找此问题,或者询问是否有人遇到过类似问题,我将不胜感激。

一些可能会有所帮助的附加说明(如果我提出问题询问失礼,请原谅。我也很乐意接受您对此的反馈:)

  • 此 tableView 是嵌入在 UINavigationController 中的 UITableViewController 的一部分

  • tableView 有 3 个部分,其中 2 个部分从视图中隐藏(0 行,无页脚,无页眉),而我正在按所述显示按钮单元格行的部分。

  • 在演示过程中,我正在通过以编程方式更改按钮的水平约束来调整按钮的位置。

  • 我的customUITableViewCelltableViewRowsUIButton的高度分别等于60.0f

【问题讨论】:

  • 作为一个实验,尝试使用CGPointMake(5,5) 而不是CGPointZero。这有什么区别吗?
  • 顺便说一句 - 如果那个小实验不起作用,请用两张截图更新您的问题。一种是有效的时候,一种是无效的时候。
  • 嗯,我很喜欢。谢谢rmaddy,这似乎可以解决问题,您能否详细说明我做错了什么?我很高兴得到修复,但很想知道原因。
  • 我还没有测试过,但是如果你在其中传递一个 CGPoint,你可能会得到一个部分页眉或页脚的 nil indexPath。
  • 鉴于您使用的是CGRectZero 并且btnPositiony 坐标是一个奇怪的值(44.009995 而不是44),我怀疑您可能有有一个边缘情况或成为舍入错误的受害者。通过选择不在视图绝对角落的点,您可以更好地避免舍入问题。

标签: ios objective-c uitableview nsindexpath


【解决方案1】:

试试这个:

修复目标选择器:

[button addTarget:self action:@selector(buttonPressed:event:)forControlEvents:UIControlEventTouchUpInside];


- (void)buttonPressed:(id)sender event:(id)event{
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchPos = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:touchPos];
    if(indexPath != nil){
        //do operation with indexPath
    }
}

【讨论】:

  • 漂亮而聪明的答案。
【解决方案2】:

我觉得我会为此获得积分,但@rmaddy 的comment 为我的代码创造了奇迹。我想把这个作为答案,因为我第一次错过了他的评论并且花了很长时间实施更长的修复。感谢 rmaddy 的修复:

作为一个实验,尝试使用 CGPointMake(5,5) 代替 CGPointZero。 这有什么不同吗?

rmaddy 然后explained 为何有效:

鉴于您使用的是 CGRectZero 并且 y btnPosition 的坐标是一个奇怪的值(44.009995 而不是 44),我怀疑你可能有边缘案例或受害者 舍入误差。通过选择一个不是绝对值的点 视图的一角,您有更好的机会避免舍入 问题。

rmaddy - 这个问题已经困扰我 2 周了......你解决了它。非常感谢。我可以将stackoverflow上的任何积分捐赠给您吗?

【讨论】:

  • 这对我也有用。到目前为止,这真是令人头疼。谢谢!
【解决方案3】:

我将分享我执行此类功能的方式。如果您有一个部分,这将起作用。你不需要这两行:

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

在您的 cellForRowAtIndexPath 添加自定义单元格时添加以下行:

cell.btn.tag = indexPath.row;
[button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

在 buttonPressed 中这样做:

-(void)buttonPressed:(UIButton *)sender{
    UIButton *btn = (UIButton *)sender;
    //Remove the btn.tag number row.
}

对于超过 1 个部分,您可以这样做:

-(void)buttonPressed:(UIButton *)sender{
    UIButton *btn = (UIButton *)sender;
    UITableViewCell *cell = (UITableViewCell *)btn.superview;
    UITableView *tableView = (UITableView *)cell.superview;
    NSIndexPath *indexPath = [tableView indexPathForCell:cell];
    //Remove this cell in indePath
}

希望这会有所帮助.. :)

【讨论】:

    【解决方案4】:

    UITapGestureRecognizer 添加到 UIButton 并为 GestureObject 添加一个目标方法。

    UITapGestureRecognizer *tapGestureDelete=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(callAMethod:)];
        [yourDeleteButton addGestureRecognizer:tapGestureDelete];
    

    在taget callAMethod中检索手势位置如下

    -(void)callAMethod:(UIGestureRecognizer *)gestureRecognizer
    {
    NSIndexPath *currentIndexPath = [self.tableView indexPathForRowAtPoint:[gestureRecognizer locationInView:self.talbleView]];
        if(currentIndexPath != nil) 
       { 
           // remove the cell from tableview 
       }
    }
    

    我希望它会工作......

    【讨论】:

      【解决方案5】:

      simalone 在 Swift(截至 2.2 版)中的回答是:

      tableViewCell.button.addTarget(self, action: #selector(buttonPressed(_:event:)), forControlEvents: .TouchUpInside)
      ...
      @IBAction func buttonPressed(sender: UIButton, event: UIEvent) {
          if let touchPos = event.allTouches()?.first?.locationInView(self.TableView),
             let indexPath = self.TableView.indexPathForRowAtPoint(touchPos)?.row {
                  // do operations with indexPath
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-22
        • 1970-01-01
        • 2011-08-19
        • 1970-01-01
        • 2020-09-14
        相关资源
        最近更新 更多