IndexPathForCell 和 IndexPathForRowAtPoint 崩溃

Posted

技术标签:

【中文标题】IndexPathForCell 和 IndexPathForRowAtPoint 崩溃【英文标题】:IndexPathForCell and IndexPathForRowAtPoint crash 【发布时间】:2013-04-22 22:27:03 【问题描述】:

我有 UITableViewController 带有静态分组单元格。在特定视图中,我想删除一些单元格。如果我只是隐藏它们,它会留下一个空白空间,所以我想将单元格的 rowHeight 设置为 0 。我在执行此操作时遇到了麻烦,因为我似乎无法获得要隐藏的单元格的 indexPath。我通过 IB 连接引用了它。阅读后,似乎最好的方法是通过heightForRowAtIndexPath 方法。这是我的代码:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    NSIndexPath *myIndexPath = [self.tableView indexPathForRowAtPoint:self.billToPostalCell.center]; 
    //crashes here

    if ([indexPath isEqual:myIndexPath]) 
        return 0; 
    
    return 44;

在此之前,我正在尝试IndexPathForCell,但也会崩溃。根据我的阅读,heightForRowAtIndexPath 应该可以工作,即使单元格不可见。当它崩溃时,调试器中也没有任何显示。

【问题讨论】:

你试过注销myIndexPath返回的行吗? 【参考方案1】:

你正在做的是导致无限递归导致......等待它......堆栈溢出!

heightForRowAtIndexPath: 方法中,您不能向表格询问单元格或向索引路径询问行,因为这些方法需要知道单元格的高度。所以这些调用导致heightForRowAtIndexPath: 被调用。而且由于您随后再次调用了相同的违规方法,因此这种情况一直持续到事情进展顺利。

由于您的目标是隐藏单元格,因此您应该使用正确的 UITableView 方法 (deleteRowsAtIndexPaths:withRowAnimation:) 从表格中删除单元格。当然,您需要先更新您的数据模型(以删除行)。

【讨论】:

谢谢,我具体如何先更新数据模型?这些是静态单元格,其中包含 IB 连接的 UITextField 和 UILabel,它们在 viewWillAppear 方法中单独填充。仅调用 deleteRowsAtIndexPaths:withRowAnimation 方法就会引发此错误:'NSInternalInconsistencyException',原因:'无效更新:第 4 节中的行数无效。从谷歌搜索,我知道我需要按照你说的更新数据源模型。 您的“numberOfRowsForSection”方法应根据您拥有的某些数据模型返回一个数字(未硬编码为某个特定值)。这是您需要更新的数据模型。这通常是某种数组。先从数组中删除对象,然后告诉表删除行。 就是这样。在这种情况下,没有数组。 tableView 的 dataSource 委托未连接视图控制器。而且我没有实现任何 dataSource 委托的方法。在 IB 中绘制的每个单元格都有一个通过 IB 出口连接到代码的 textField。然后在代码中,我像这样填充文本字段:self.myTextField.text = self.customer.someString。在删除行之前,我尝试将单元格设置为零,但没有骰子。 我找到了这个答案,它对我的​​后续问题有所帮助。 ***.com/a/9434849/1672161 感谢您回答我最初的问题。【参考方案2】:

您不应该更改单元格的可见性和高度。如果您想删除单元格并稍后添加它们,或者永远不要添加它们,您应该使用 UITableView 上的插入和删除方法。这是一个很好的起点documentation。

此外,您不应该在tableView:heightForRowAtIndexPath: 中使用tableView 上的方法,例如indexPathForRowAtPoint:,因为tableView 必须先计算出自己的高度,然后才能计算出这样的东西。您可能会遇到错误,因为您处于无限循环中。

【讨论】:

【参考方案3】:

使用-deleteRowsAtIndexPaths:withRowAnimation 删除行。切勿操纵单元格的可见性来代替删除它;这可能会导致严重的内存问题,并且只是一般的不良做法。只需传入一个 NSArray 填充您要删除的行的 NSIndexPath

您提到indexPathForRowAtPoint: 方法不起作用。这几乎肯定是您传递给它的点的问题。请务必注销 billToPostalCell.center 的值,以确保您传递的是合法值。但是,如果您正在处理静态单元格,则确实不需要这样做,因为您应该已经知道索引路径(至少对于初始单元格删除而言)。

正如其他人所提到的,关于删除单元格的documentation 提供了您应该需要的所有其他信息。

【讨论】:

这是一个我忘了提的好点,因为您使用的是静态单元格,只需与静态 indexPath.row 进行比较即可。

以上是关于IndexPathForCell 和 IndexPathForRowAtPoint 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

重新加载UITableView数据后,indexPathForCell返回null

self.tableView.indexPathForCell(cell) 返回错误的单元格?

在单元格中单击时,tableView:indexPathForCell 返回 nil

UITableViewCell indexPathForCell:iOS 7 上的应用程序崩溃

indexPathForCell 在 IOS 7 下返回 NULL,在 IOS 6 下工作正常

UITableView indexPathForCell:在iOS10中使用Xcode8(Swift2.3)返回nil