iOS 7 上的 NS 合并冲突
Posted
技术标签:
【中文标题】iOS 7 上的 NS 合并冲突【英文标题】:NSMergeConflict on iOS7 【发布时间】:2013-10-04 10:25:24 【问题描述】:我已经更新了我的应用程序以支持 ios 7,并且遇到了在我的 [context save];
的一个屏幕上出现以下错误的问题:
NSCocoaErrorDomain Code=133020 "The operation couldn’t be completed. (Cocoa error 133020.)" UserInfo=0x1115a6d0 conflictList=(
"NSMergeConflict (0x1115a670) for NSManagedObject (0xf25c850) with objectID '0xf25c070 <x-coredata://76AF57C8-F7FF-4880-B06B-63F8B780C96D/Screen/p7>' with oldVersion = 5 and newVersion = 6
and old object snapshot = \n index = 3;\n message = \"<null>\";\n status = 0;\n and new cached row = \n index = 3;\n message = \"<null>\";\n status = 0;\n"
在 iOS6 上不会出现此问题。
更新: managedObjectContext 的代码
-(NSManagedObjectContext *)managedObjectContextForCurrentThread
if ([NSThread isMainThread])
NSManagedObjectContext *parentContext = self.mainManagedObjectContext.parentContext;
[parentContext performBlockAndWait:^
NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
[[self mainManagedObjectContext] setMergePolicy:mergePolicy];
];
return self.mainManagedObjectContext;
else
NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];
NSManagedObjectContext *threadContext = [threadDict objectForKey:kCGMManagedObjectContextKey];
if (threadContext == nil)
threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSManagedObjectContext *parentContext = self.mainManagedObjectContext.parentContext;
[parentContext performBlockAndWait:^
NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
[parentContext setMergePolicy:mergePolicy];
];
[threadContext setParentContext:self.mainManagedObjectContext];
[threadDict setObject:threadContext forKey:kCGMManagedObjectContextKey];
return threadContext;
【问题讨论】:
跟我遇到的问题一模一样,你有什么解决办法吗?我不明白为什么会出现这个问题,iOS 6 没有抱怨。在我的情况下,我看不出为什么会发生这种情况,因为我正在编辑的 ManagedObject 来自我正在保存的同一个 ManagedObjectContext,它为什么要抱怨合并错误? 【参考方案1】:我只花了两天时间调试完全相同的错误。你的应用和我的区别在于我的应用只从主线程访问核心数据,所以合并错误更令人费解。
在我们的例子中,我把它缩小到我们有一个单向关系的事实 - A 有很多 B(建模为 NSSet),但 B 不知道它的 A。我们有一个修改 A 和a B,并且在我们保存这些更改时会导致合并错误。此代码在 iOS 5 和 6 上运行了很长时间,但在 iOS 7 上才开始失败。
确实,添加合并策略会使错误消失,但它也可能掩盖其他错误。在我们的例子中,我们宁愿看到这些错误,也不愿冒着数据库不一致的风险。
将关系更改为双向使错误消失。我们的应用程序不需要反向链接,但它们也没有伤害。 (令人高兴的是,更改这种关系作为轻量级迁移得到了正确处理 - 核心数据自动为我们填充了这些反向链接。)
【讨论】:
我遇到了完全相同的问题,这帮助我解决了它! NSMergeConflict 不是很清楚:/ 还记得在核心数据编辑器中设置“反向”字段。我们在应用程序中有双向关系,但开发人员忘记正确设置 Inverse,这导致了这种伪冲突。【参考方案2】:根据苹果的文档
NSManagedObjectMergeError = 133020
此错误代码表示合并策略失败 - Core Data 无法完成合并。
您的代码中是否有任何合并策略?请尝试 NSMergeByPropertyObjectTrumpMergePolicy。
[self.context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
【讨论】:
【参考方案3】:使用带有 Apple Watchkit 扩展的 Xcode 6.3.2,我在尝试进行多次更新和保存时遇到了同样的错误。 setMergePolicy 解决了这个问题,这里是 swift 代码:
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
确保将上述行放在 context.save 命令之前。
【讨论】:
使用 Swift,这完美地解决了基本相同的问题。谢谢! 我不会从来没有遇到过这个!甚至不想知道这行代码为我节省了多少小时的阅读和故障排除时间。【参考方案4】:我不想在不了解导致 NSMergeConflict
首先的原因的情况下通过设置合并策略来掩盖潜在问题。
在我的情况下,我早些时候在我的代码中执行了NSBatchDeleteRequest
。 NSBatchDeleteRequest
直接在持久存储协调器上执行,因此ManagedObjectContext
不知道删除并仍然持有对已删除对象的引用。当我后来引用其中一个对象并尝试保存上下文时,NSMergeConflict
被抛出。
执行删除后在我的moc
上调用reset()
解决了问题。
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Tasks")
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
try managedContext.execute(batchDeleteRequest)
managedContext.reset()
【讨论】:
【参考方案5】:我遇到了类似的错误,就我而言,锁定 NSPersistentStoreCoordinator 有效。
[context.persistentStoreCoordinator lock];
[context performBlockAndWait:^
// do something
];
[context.persistentStoreCoordinator unlock]
我不知道它为什么起作用,但我怀疑 NSManagedObjectContext 的错误。 我希望这会有所帮助。
【讨论】:
【参考方案6】:我在使用完整存储进行测试时得到了这个。因此,似乎任何类型的合并失败(在我的情况下,存储已满并且无法更新持久存储)都会产生这种情况。
【讨论】:
以上是关于iOS 7 上的 NS 合并冲突的主要内容,如果未能解决你的问题,请参考以下文章