【问题标题】:NSFetchedResultsController is driving me crazyNSFetchedResultsController 快把我逼疯了
【发布时间】:2010-03-14 16:40:07
【问题描述】:

自 1 个月以来,我一直在使用 NSFetchedResultsController 构建一个应用程序,并且我正在 3.1.2 SDK 上测试该应用程序。问题是我一直在我的应用程序中使用 NSFetchedResultsController 并且正在开发 3.1.2 版本的 SDK,现在我的客户说我应该让它与 3.0 版本兼容并且截止日期快到了。

但是每次我更改控制器处理的对象时都会崩溃,应用程序会崩溃并出现非常奇怪的错误。

在删除部分中的最后一个对象以及更改使对象爱到另一个部分时会出现问题。

我一直在使用 Dave Mark 和 Jeff LaMarche 的“More iPhone 3 Development Tackling iPhone SDK 3”中的示例代码。我还包含了来自link text的一些更改

这是应用程序崩溃时控制台的示例输出。

*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:无效的节数。更新后表视图中包含的节数(1)必须等于更新前表视图中包含的节数(2),加上或减去插入或删除的节数(2插入,0已删除)。 2010-03-14 16:23:29.758 Instaproofs [5879:207] 堆栈:( 807902715, 7364425, 807986683, 811271572, 815059090, 815007323, 211023, 4363331, 810589786, 807635429, 810579728, 3620573, 3620227, 3614682, 3609719, 27337, 810595174, 807686849, 807683624, 839142449, 839142646, 814752238 )

如果我知道 NSFetchedResultsController 有这么多 bug,我永远不会使用它。

所以基本上我需要我的 NSFetchedResultsControllerDelegate 在 3.0 及更高版本的 SDK 上正常工作。

如果有人帮我弄清楚我做错了什么,那将是救命稻草。

【问题讨论】:

    标签: iphone nsfetchedresultscontroller


    【解决方案1】:

    从您的错误消息中可以看出,当您应该删除节时,您正在将节插入表中。您的 tableView 数据源在更新后仅提供一个部分,即使您已告诉 tableView 期望总共有四个部分。

    我不认为这是 NSFetchedResultsController 存在错误的情况,而是在简单的用例之外实现起来很棘手。由于您的控制器:didChangeObject:atIndexPath:forChangeType:newIndexPath 委托方法,您的崩溃几乎肯定会发生。成功实现此方法的关键(至少在我的经验中)是要记住 changeTypes 是对象和 indexPath 驱动的。这使得“更新”和“移动”在概念上变得棘手。

    考虑这样一种情况,其中托管对象被更改,以便它在新的 sectionNameKeyPath 下排序。从概念上讲,我们认为该对象已“移动”到新部分,因为 fetchedResultsController 现在将其排序到 tableView 中的新标题下。但是,如果对象的 indexPath 没有改变,那么 fetchedResultsController 会认为这是“更新”而不是“移动”。

    更糟糕的是,即使更改的托管对象仍然保留相同的 indexPath,fetchedResultsController 中的其他对象现在可能有新的 indexPaths,因为它们被更改碰撞。这意味着您必须在委托方法的“更新”部分中手动处理部分插入和部分删除。类似的问题需要在您的委托方法的“移动”部分解决。

    LaMarche 的解决方案没有试图用太多的语言来解释它,而是试图以一种通用的方式来解决这个问题,以适应尽可能多的用例。通过尝试理解与您的用例相关的问题,您可能能够显着降低 LaMarche 使用的代码的复杂性。特别关注委托方法的“更新”和“移动”部分,因为它们最有可能是造成问题的罪魁祸首。

    【讨论】:

    • 注意:我知道 NSFetchedResultsController 的 3.0 版本中存在一个错误,并且在类参考文档中有所提及。该错误只是一个问题,您没有指定 sectionNameKeyPath。不过,为了安全起见,您可能希望实施文档中提供的解决方法。
    • 上面的帖子非常有帮助。我和原始海报有同样的问题。我发现在 - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath 发生任何变化后重新加载数据最有效的时间,虽然不是 100% 的时间。我不知道这有多重要。但希望它对遇到这篇文章的人有所帮助。
    【解决方案2】:

    【讨论】:

      猜你喜欢
      • 2011-12-11
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多