我如何使用 NSFetchResultsController 正确处理 context.rollback()

How do i correctly handle context.rollback() with an NSFetchResultsController

我有一个为 UITableView 提供数据的 NSFetchResultsController。我在导航栏中有一个添加按钮,允许用户在下一个视图中添加一个新实体。

在下一个视图中,我创建了一个新实体并将其插入到上下文中。然后用户可以保存此更改。但是,如果用户决定不保留这个新实体,他们可以点击取消,然后我调用 context.rollback() 来删除新实体。这导致我的 fetchresultscontroller 抛出异常:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).

这是我有两个实体时显示的错误,我创建了第三个实体并点击取消。

当我在另一个视图上执行回滚时,异常被抛出。我使用以下代码执行插入:

 let entity =  NSEntityDescription.entityForName("template",
            inManagedObjectContext: context!)
 let newTemplate = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: context) as! Template

        newWorkoutTemplate.setValue("New Template", forKey: "name")

        self.template = newWTemplate

我在执行此插入之前设置了上下文的撤消管理器。 为什么 NSFetchResultsController 没有检测到新实体的插入,但在执行回滚时检测到它的删除?是因为插入和删除都是对同一个实体进行的吗?

我意识到我已经在我原来的 VC 中实现了一个 didChangeObject fetchResultControllerDelegate 方法,这就是罪魁祸首。该行

            templatesTable.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Fade)
当另一个 VC 呼叫 context.rollback()

时正在呼叫

所以我通过在我的第一个 VC 中添加一个 bool inAnother 来解决这个问题。最初我将其设置为 false。当我转到另一个视图时,我将其设置为 true。然后,当在另一个视图中发生回滚时,我的 fetchController 的 didChangeObject 被调用。在 didChangeObject 内,我检查我是否在另一个视图中,如果我在:

,则不执行任何操作
if (!inAnother && type == NSFetchedResultsChangeType.Delete) {

        templatesTable.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Fade)

}

此外,我在第一个 VC 的 viewWillAppear() 中将 inAnother 设置回 false 以确保行删除继续正常运行。