首页 文章

如何使用NSFetchedResultsController处理节插入?

提问于
浏览
0

我有一个NSFetchedResultsController作为我的数据源,我在自定义UITableViewController中实现NSFetchedResultsControllerDelegate . 我正在使用sectionNameKeyPath将我的结果集分成多个部分 .

在我的一个方法中,我在上下文中添加了几个对象,所有这些都在新的部分中 . 在保存对象的那一刻,委托方法被正确调用 . 事件顺序:

// -controllerWillChangeContent: fires
[self.tableView beginUpdates]; // I do this

// -controller:didChangeSection:atIndex:forChangeType: fires for section insert
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]];

// -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath fires many times
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                withRowAnimation:UITavleViewRowAnimationFade]; // for each cell

// -controllerDidChangeContent: fires after all of the inserts
[self.tableView endUpdates];  // <--- Where things go terribly wrong!!!

在最后一次调用“endUpdates”时,应用程序总是崩溃:

Serious application error.  Exception was caught during Core Data change processing:
[NSCFArray objectAtIndex:]: index (5) beyond bounds (1) with userInfo (null)

似乎表更新在某种程度上与NSFetchedResultsController数据不同步,事情就好了 . 我正在关注NSFetchedResultsControllerDelegate上的文档,但它无法正常工作 . 什么是正确的方法呢?

UPDATE: 我创建了一个展示此bug的测试项目 . 您可以在以下位置下载:NSBoom.zip

2 回答

  • 0

    通过应用程序进行跟踪,我注意到首先调用didChangeSection,它会插入整个部分 - 然后重复调用didChangeObject .

    问题是在didChangeSection中插入整个部分,然后在更新表视图之前,您将对象添加到同一部分 . 这基本上是重叠更新的情况......(即使在开始/结束更新块中也不允许) .

    如果您注释掉单个对象插入,则一切正常:

    case NSFetchedResultsChangeInsert:
                [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                 withRowAnimation:UITableViewRowAnimationFade];
                break;
    

    如果你注释掉插入部分,它就不起作用 - 但是我一直没有运行insertRowsInSections,这可能是因为还没有部分(我确定你插入的原因)开头的部分) . 您可能必须检测任何一种情况以使用正确的粒度进行插入 .

    一般来说,我有更多的运气重新加载和插入整个部分而不是行,表格视图对我来说非常繁琐 . 您还可以尝试UITableViewRowAnimationNone,它似乎可以更频繁地运行 .

  • 1

    我遇到了同样的问题 . 我发现didChangeSection发射了两次 . 一旦你创建了插入对象,一旦你实际保存它 . 对我来说,在调用save之前不应该调用didChangeSection . 或者至少,将在创建对象时调用willChangeSection,并在保存时调用didChangeSection .

    现在我正在研究NSManagedObjectContextDidSaveNotification观察者方法 . 这不是NSFetchedResultsControllerDelegate协议的一部分,但您可以注册接收它 . 也许这只会在我实际调用save而不是之前调用时调用 .

相关问题