indexPathForRowAtPoint仅为uitableview中的第一个单元格返回nil

时间:2014-03-13 03:33:33

标签: ios objective-c uitableview nsindexpath

我在自定义UIButton内部有一个UITableViewCell,当按下该按钮时会移除该单元格。为了获取按钮所在单元格的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. 我按下第一个单元格按钮:按钮被调用但indexPath为零,所以没有任何反应。
  2. 我按下第三个单元格按钮:调用 buttonPressed并按预期删除单元格。
  3. 我再次按下第一个单元格:与之前相同,buttonPressed被调用但indexPath为nil。
  4. 我按下第二个单元格按钮:调用 buttonPressed并按预期删除单元格。
  5. 我按下第一个单元格按钮:这次调用了buttonPressed,indexPath不是nil,并且按预期删除了单元格。
  6. 我已经检查过tableView不是nil,正如相关但不同的帖子所建议的那样。我还确认,在btnPosition(x=260, y=44.009995)时,[self.tableView indexPathForRowAtPoint:btnPosition] == nil点都设置为相同的值[self.tableView indexPathForRowAtPoint:btnPosition] != nil

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

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

    我非常感谢您提供帮助,了解我可能会在哪些方面跟踪此问题,或者听到是否有人遇到类似问题。

    一些可能有帮助的补充说明(如果我提出一个问题,请原谅。请高兴地接受您的反馈意见:)

    • 此tableView是嵌入UITableViewController

    • UINavigationController的一部分
    • tableView有3个部分,其中2个部分在视图中隐藏(0行,没有页脚,没有标题),而我正如所描述的那样使用按钮单元格行显示该部分。

    • 我通过以编程方式更改其水平约束来调整演示期间按钮的位置。

    • customUITableViewCelltableViewRowsUIButton的高度均等于60.0f

5 个答案:

答案 0 :(得分:6)

试试这个:

修复目标选择器:

[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
    }
}

答案 1 :(得分:4)

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

  

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

rmaddy然后explained为什么会有效:

  

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

rmaddy - 这个问题困扰了我2个星期......你修好了。非常感谢你。我可以在stackoverflow上捐赠任何积分吗?

答案 2 :(得分:1)

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

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
}

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

答案 3 :(得分:1)

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 
   }
}
     

我希望它会起作用......

答案 4 :(得分:0)

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
    }
}