自 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
进行了一些更改这是应用程序崩溃时控制台的示例输出。
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number of sections inserted or deleted (2 inserted, 0 deleted).'
2010-03-14 16:23:29.758 Instaproofs[5879:207] Stack: (
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 上正常工作。
如果有人帮助我找出我做错了什么,这将是我的救星。
从您的错误消息中可以看出,您在应该删除部分时却将其插入了表中。 即使您已告诉 tableView 总共需要四个部分,您的 tableView 数据源在更新后仅提供一个部分。
我不认为这是 NSFetchedResultsController 有问题的情况,而是在简单用例之外实现起来很棘手。 您的崩溃几乎肯定是由于您的controller:didChangeObject:atIndexPath:forChangeType:newIndexPath 委托方法而发生的。 成功实现此方法的关键(至少根据我的经验)是要记住changeTypes 是对象和indexPath 驱动的。 这使得“更新”和“移动”在概念上变得棘手。
考虑托管对象发生更改以使其在新的sectionNameKeyPath 下排序的情况。 从概念上讲,我们认为该对象已“移动”到新部分,因为 fetchedResultsController 现在将其排序在 tableView 中的新标题下。 但是,如果对象的 indexPath 没有更改,则 fetchedResultsController 会认为这是“更新”而不是“移动”。
更糟糕的是,即使更改的托管对象仍然保留相同的索引路径,fetchedResultsController 中的其他对象现在可能具有新的索引路径,因为它们因更改而受到影响。 这意味着您必须在委托方法的“更新”部分中手动处理部分插入和部分删除。 类似的问题需要在委托方法的“移动”部分中解决。
LaMarche 的修复方法并没有试图用太多的语言来解释它,而是尝试以一种通用的方式来解决这个问题,以适应尽可能多的用例。 通过尝试理解与您的用例相关的问题,您也许能够显着降低 LaMarche 使用的代码的复杂性。 特别关注委托方法的“更新”和“移动”部分,因为这些是最有可能导致问题的罪魁祸首。