我有一个辅助托管对象上下文,在该数据合并回主moc之前处理传入的同步数据。不幸的是,我遇到了似乎是合并政策问题的问题。问题发生在将通知合并回主moc时,而不是在此之前...当辅助上下文保存自己时。
辅助上下文的合并策略是NSMergeByPropertyObjectTrumpMergePolicy。如果我删除此策略并将其默认恢复为典型错误,则不再出现此问题。但是,我试图理解为什么这是一个问题,特别是因为我不想在这个上下文中使用默认的合并策略。
我有一个具有活动属性的User对象。当同步对象从重新激活用户的服务器进入时,流程如下:
在将更改应用于对象之前,这是它的初始状态:
(SyncObject *) $29 = 0x0051b6f0 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 0;
...
将更改应用于对象后,正如人们所期望的那样:
(SyncObject *) $30 = 0x0051b6f0 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 1;
...
稍后,在保存之前,我验证了对象仍处于活动状态(这是一个int,因为我在这种情况下直接使用了内存地址):
(int) $45 = 5355248 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 1;
...
接下来我们有保存:
[syncContext save:&error];
然后在合并通知块中,当我打印通知时,我看到了这一点:
updated = "{(\n <User: 0x51b6f0> (entity: User;
id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ;
data: {\n active = 0;\n
...
更糟糕的是,此时的对象显示如下:
(int) $47 = 5355248 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 0;
...
为什么内存中的对象似乎被SQL存储中的数据覆盖?据我了解,NSMergeByPropertyObjectTrumpMergePolicy意味着内存中的不同值将保存在商店中的那些值之上,但显然不是正在发生的事情。我真的很茫然,这个问题让我很担心,因为它似乎表明服务器上发生的变化可能会被抛弃。如果有人知道这里发生了什么,我很想知道实际发生了什么。
我应该提一下,当我删除合并策略时,这个保存会抛出合并错误,正如我所料,但是我不明白为什么它认为我的新更改为“旧”
(NSError *) $8 = 0x00566720 Error Domain=NSCocoaErrorDomain Code=133020 "The operation couldn’t be completed. (Cocoa error 133020.)" UserInfo=0x591c90 {
conflictList=(
"NSMergeConflict (0x5df220) for NSManagedObject (0xd63a370) with objectID '0xd635310 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617>'
with oldVersion = 9 and newVersion = 10
and old object snapshot = {\n active = 1;\n ...\n}
and new cached row = {\n active = 0;\n ... \n}"
)}
解决方法:
因此,在我的情况下,这是因为在主要托管对象上下文中对此特定对象进行了更改。因为我们有一个Core Data Watcher类正在运行(监听上下文保存通知),所以我需要在合并新的MOC之前保存对该MOC的所有更改,以便正确记录用户更改。我 在mergeChangesFromContextDidSaveNotification调用之前在NSManagedObjectContextDidSaveNotification块中执行此操作,这对于停止冲突来说已经太晚了。通过将其移动到NSManagedObjectContextWillSaveNotification,mainMOC将其更改保存到持久性存储,观察者注册这些更改,然后辅助存储可以自由尝试将其更改合并到mainMOC中,而不用担心与后者可能排队的更改冲突起来。
作为对此的一个警告,我必须确保在我获取对象以更新传入的同步上下文之前,我已经保存了对主上下文中这些对象的任何挂起的更改。最终结果是我在保存之前拍摄了对象的快照,因此我在一个上下文中所做的更改与在另一个上下文中准备的更改不同步。虽然我仍然模糊为什么合并发生的方式,通过确保我在尝试更改它并将其合并回来之前拥有对象的最新版本,合并错误消失了并且合并过程继续进行。