解析RestKit中的CoreData合并冲突,当上下文保存对象更新而另一个正在删除对象时

时间:2012-05-14 18:02:09

标签: core-data concurrency merge restkit nsmanagedobjectcontext

假设我有一个名为«Picture»的NSManagedObject,我是通过RestKit创建的。 我正在通过NSOperation上传实际的图片文件内容。 NSOperation正在跟踪上传进度,并将其保存在Picture对象的«progress»属性中。

if(![self isCancelled]) {
    Picture *pic = [Picture findFirstByAttribute:@"pictureId" withValue:self.pictureId];
    if(![pic isDeleted]) {
        pic.progress = [NSNumber numberWithFloat:progress];
        [[RKObjectManager sharedManager].objectStore save:NULL];
    }
}

我的视图控制器在NSFetchedResultsController的帮助下显示Picture对象列表。 上传效果很好,RestKit正在执行线程安全并且合并回主NSManagedObjectContext,因此UI正在按预期显示上传进度。

现在想象一下,在上传图片时,用户按下“取消”十字,这也应该删除图片对象。 在控制器中,我在NSOperation上调用取消,它在几毫秒内有效地停止运行操作,并且在主线程上从CoreData中删除该对象。

[uploadOperation cancel];
Picture *pic = [Picture findFirstByAttribute:@"pictureId" withValue:self.pictureId];
[pic deleteEntity];
[[RKObjectManager sharedManager].objectStore save:NULL];

Traces显示我按照预期在NSFetchedResultsControllerDelegate上获得了NSFetchedResultsChangeDelete。然而,紧接着是NSFetchedResultsChangeInsert和NSFetchedResultsChangeUpdate,因为NSOperation经常保存进度。 似乎NSOperation使用的NSManagedObjectContext不同步。它不知道Picture对象被删除,对save的调用:导致插入和更新。

因此,在我的UI(以及数据库)中,我的Picture对象仍然存在,而它应该被删除。

看看RKManagedObjectStore,似乎合并是从后台线程(NSOperation)到主线程(我的视图控制器),但不是相反的方式。

解决此问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

听起来像是使用Core Data Undo Manager的完美情况。您将找到一个很好的示例over here或Apple提供的CoreDataBooks示例。

答案 1 :(得分:0)

我认为您应该稍微改变应用程序的控制流程。在NSOperation仍在进行中时删除主上下文中的对象听起来像个坏主意。为什么不例如检查操作是否在NSOperation本身被取消并使用其MOC从那里删除图像对象?通过这种方式,您只能在一个子MOC上写入。另外,在每次修改之前更新操作中的子MOC都会破坏具有单独上下文的目的。

考虑到这一点,可能有一些聪明的方法来观察NSManagedObjectContextObjectsDidChangeNotification并与适当的NSMergePolicy合并,但话说回来,我认为这对你的案子来说太过分了。我只是在同一个地方处理整个取消和删除。