我一直在阅读有关merge policies的内容,它给出了关于何时合并更改的相互矛盾的想法。
我有两个上下文 - 一个在后台队列中,一个在主队列中。两者都有定义了NSOverwriteMergePolicy的策略,我认为这是完全错误的。我已经遇到了同步问题。我经常看到,在服务器数据的后台同步中,我的NSManagedObjects经常过时,我最终保存它们,导致数据丢失。
是否有任何地方可以访问所有规则&上下文保存的优先顺序,关于覆盖策略的上下文刷新?
我已经看到了有关合并政策的所有文档,但我很困惑它们是否在SAVE或REFRESH上生效。
而且,在某种程度上,这非常令人困惑。例如,Apple Docs为NSMergeByPropertyObjectTrumpMergePolicy
:
合并持久性商店版本之间冲突的策略 对象和当前的内存版本由个人 属性,外部变化胜过内存中的变化。 合并由个人财产发生。
对于已在外部源和内存中更改的属性,在内存中 改变胜过外部的。
当我选择在不同的上下文中修改/不修改它们时,如何确保我所需的属性被修改/保持不受影响?
答案 0 :(得分:1)
TL:DR:合并政策是邪恶的。您只应以同步方式写入核心数据。
完整说明:如果某个对象同时从两个不同的上下文更改,则核心数据不知道该怎么做。您可以设置mergePolicy来设置哪个更改应该获胜,但这确实不是一个好的解决方案,因为您将以这种方式丢失数据。许多专业人员长期处理这个问题的方式是有一个操作队列来排队写入,所以一次只能进行一次写入,并且主线程上只有读取的上下文。这样你就不会遇到任何合并冲突。 (有关此设置的详细说明,请参阅https://vimeo.com/89370886)。
使用NSPersistentContainer
进行此设置非常简单。在核心数据管理器中创建一个NSOperationQueue
_persistentContainerQueue = [[NSOperationQueue alloc] init];
_persistentContainerQueue.maxConcurrentOperationCount = 1;
使用这个队列写所有内容:
- (void)enqueueCoreDataBlock:(void (^)(NSManagedObjectContext* context))block{
void (^blockCopy)(NSManagedObjectContext*) = [block copy];
[self.persistentContainerQueue addOperation:[NSBlockOperation blockOperationWithBlock:^{
NSManagedObjectContext* context = self.persistentContainer.newBackgroundContext;
[context performBlockAndWait:^{
blockCopy(context);
[context save:NULL]; //Don't just pass NULL here. look at the error and log it to your analytics service
}];
}]];
}
当你调用enqueueCoreDataBlock
时,该块被排队以确保没有合并冲突。但是如果你写viewContext
那会破坏这种设置。同样,您应该将您创建的任何其他上下文(使用newBackgroundContext
或performBackgroundTask
)视为只读,因为它们也将位于写入队列之外。