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

时间:2015-07-14 12:35:19

标签: ios swift uitableview nsfetchedresultscontroller

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

在下一个视图中,我创建了一个新实体并将其插入到上下文中。然后,用户可以保存此更改。但是,如果用户决定不保留这个新实体,他们可以点击取消,我打电话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没有检测到新实体的插入,但在执行回滚时检测到它的删除?是因为插入和删除都是在同一个实体上执行的吗?

1 个答案:

答案 0 :(得分:0)

我意识到我已经在原来的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的inAnother中将viewWillAppear()设置为false,以确保行删除继续正常运行。