假设我有一个名为«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)到主线程(我的视图控制器),但不是相反的方式。
解决此问题的最佳方法是什么?
答案 0 :(得分:0)
听起来像是使用Core Data Undo Manager的完美情况。您将找到一个很好的示例over here或Apple提供的CoreDataBooks示例。
答案 1 :(得分:0)
我认为您应该稍微改变应用程序的控制流程。在NSOperation仍在进行中时删除主上下文中的对象听起来像个坏主意。为什么不例如检查操作是否在NSOperation
本身被取消并使用其MOC从那里删除图像对象?通过这种方式,您只能在一个子MOC上写入。另外,即在每次修改之前更新操作中的子MOC都会破坏具有单独上下文的目的。
考虑到这一点,可能有一些聪明的方法来观察NSManagedObjectContextObjectsDidChangeNotification
并与适当的NSMergePolicy
合并,但话说回来,我认为这对你的案子来说太过分了。我只是在同一个地方处理整个取消和删除。