2

假设我有一个名为 «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 的帮助下,我的视图控制器正在显示图片对象列表。上传效果很好,RestKit 正在执行线程安全并合并回主 NSManagedObjectContext,因此 UI 按预期显示上传进度。

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

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

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

因此,在我的 UI(和 DB)中,我的 Picture 对象在它应该被删除时仍然存在。

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

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

4

2 回答 2

0

听起来像是使用核心数据撤消管理器的完美情况。您可以在此处或 Apple 提供的 CoreDataBooks 示例中找到一个很好的示例。

于 2012-11-19T21:11:29.957 回答
0

我认为您可能应该稍微更改应用程序的控制流程。在 NSOperation 仍在进行时删除主上下文中的对象听起来是个坏主意。你为什么不检查操作本身是否被取消NSOperation并使用它的 MOC 从那里删除图像对象?这样,您只能在一个子 MOC 上进行写入。另一种选择,在每次修改之前更新操作中的子 MOC,这违背了拥有单独上下文的目的。

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

于 2013-06-03T19:56:47.887 回答