UITableView 方法“indexPathForRowAtPoint:”的奇怪行为

Posted

技术标签:

【中文标题】UITableView 方法“indexPathForRowAtPoint:”的奇怪行为【英文标题】:Weird behavior of UITableView method "indexPathForRowAtPoint:" 【发布时间】:2013-06-05 17:15:20 【问题描述】:

如以下代码所示,当 tableview 被拉伸(从不向上滚动)时,NSLog(@"tap is not on the tableview cell") 将始终被调用(我认为 indexPath 将始终为 nil)。但是,当我在节号大于 2 的节标题中点击头像时,NSLog 不会被调用。很奇怪,有人知道这是怎么回事吗?

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

 ...
     UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
     tapGesture.numberOfTapsRequired = 1;
     [avatar addGestureRecognizer:tapGesture];
     //avatar is UIImageView and the user interaction is enabled.
     [headerView addSubview: aMessageAvatar];
     return headerView;
 ...




-(void)handleTapGesture:(UITapGestureRecognizer *)sender

    CGPoint point = [sender locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
    if (!indexPath) 
    NSLog(@"tap is not on the tableview cell");
    

【问题讨论】:

当您单击随后的标题时,您会说indexPath 不是nil。那么,它是什么?顺便说一句,heightForHeaderInSection: 返回的是什么?你的avatar 的高度是多少?如果您的如果您的标题视图未设置为剪辑子视图,我可以很容易地想象您认为您正在点击标题视图,但该点可能对应于它后面的一个单元格。 @Rob 是表头下的行的indexPath。表头高度为48.0f,头像框为(8, 8, 32,32)。 这很好奇,但我不确定我是否会为此担心太多。 indexPathForRowAtPoint 中的一些特质(即错误)可能无法优雅地处理在部分页眉/页脚中点击的人。这似乎不是一个非常重要的问题,因为indexPathForRowAtPoint 显然不是解决您问题的正确方法。为什么要担心您知道是错误解决方案的解决方案中的潜在错误?使用tag 是合乎逻辑的解决方案。 【参考方案1】:

您的点击位置是标题中的位置,而不是单元格,因此它永远不会匹配单元格indexPath

您可以将avatar 视图的tag 设置为viewForHeaderInSection 中的节号,然后通过sender.view.tag 检索handleTapGesture 中的节号。例如:

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

 ...
     UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
     tapGesture.numberOfTapsRequired = 1;
     avatar.tag = section;                // save the section number in the tag
     avatar.userInteractionEnabled = YES; // and make sure to enable touches
     [avatar addGestureRecognizer:tapGesture];
     //avatar is UIImageView and the user interaction is enabled.
     [headerView addSubview: aMessageAvatar];
     return headerView;
 ...



-(void)handleTapGesture:(UITapGestureRecognizer *)sender

    NSInteger section = sender.view.tag;
    NSLog(@"In section %d", section);

【讨论】:

是的,因为我认为 indexPath 总是为零,但是当我在第二次之后触摸标题时,indexPath 有一个值。 @luyuan 我觉得这很令人惊讶。但显然,在非单元格上设置点击手势然后使用生成的手势处理程序来确定您点击了哪个单元格是没有意义的。如果您正在寻找您点击的部分,您可以使用tag 方法。否则你将不得不描述你想要做什么,因为最初的概念并不完全合理。 @Rob 请检查问题***.com/questions/16945661/… @luyuan 好的。根据您的另一个问题,您似乎担心用户删除行。如果您让用户添加/删除行/部分,那么tag 可能不应该是从零开始的部分编号索引。它应该是您分配的一些唯一数字标识符。但是解决方案的根源是相同的;使用tag 跟踪您点击的标题,确保tag 唯一标识有问题的标题。

以上是关于UITableView 方法“indexPathForRowAtPoint:”的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

UITableView“cellForRowAtIndexPath”方法突然被调用两次

UITableView控件didSelectRow和didDeselectRow方法注意事项

未调用 UITableView 方法 cellForRowAtIndexPath

UITableView 方法没有触发

IOS UITableview代理方法总结

UITableView创建步骤与常用数据源方法