10

我已经更新了我的应用程序以支持 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;
}

}

4

6 回答 6

17

我只花了两天时间调试完全相同的错误。你的app和我的区别在于我的app只从主线程访问核心数据,所以合并错误更令人费解。

在我们的例子中,我把它缩小到我们有一个单向关系的事实——A 有很多 B(建模为 NSSet),但 B 不知道它的 A。我们有一个修改 A 和 B 的方法,并且在我们保存这些更改时会导致合并错误。这段代码在 iOS 5 和 6 上运行了很长时间,但在 iOS 7 上才开始失败。

确实,添加合并策略会使错误消失,但它也可能掩盖其他错误。在我们的例子中,我们宁愿看到这些错误,也不愿冒着数据库不一致的风险。

将关系更改为双向使错误消失。我们的应用程序不需要反向链接,但它们也没有伤害。(令人高兴的是,改变这种关系作为轻量级迁移得到了正确的处理——核心数据自动为我们填充了这些反向链接。)

于 2013-10-16T15:51:13.570 回答
15

根据苹果的文档

NSManagedObjectMergeError = 133020

此错误代码表示合并策略失败 - Core Data 无法完成合并。

您的代码中是否有任何合并策略?请尝试 NSMergeByPropertyObjectTrumpMergePolicy。

[self.context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
于 2013-10-04T10:50:57.493 回答
7

使用带有 Apple Watchkit 扩展的 Xcode 6.3.2,我在尝试进行多次更新和保存时遇到了同样的错误。setMergePolicy 解决了这个问题,这里是快速代码:

context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

确保将上述行放在 context.save 命令之前。

于 2015-06-08T15:44:45.600 回答
4

我不想通过设置合并策略来掩盖潜在问题,而不了解导致第一个问题的原因NSMergeConflict

在我的情况下,我NSBatchDeleteRequest之前在我的代码中执行过。NSBatchDeleteRequest直接在持久存储协调器上执行,因此不ManagedObjectContext知道删除并仍然持有对已删除对象的引用。当我后来引用其中一个对象并尝试保存上下文时,NSMergeConflict被抛出。

执行删除后打电话reset()给我解决了这个问题。moc

let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Tasks")
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
try managedContext.execute(batchDeleteRequest)
managedContext.reset() 
于 2017-09-21T09:25:38.270 回答
1

我遇到了类似的错误,就我而言,锁定 NSPersistentStoreCoordinator 有效。

[context.persistentStoreCoordinator lock];
[context performBlockAndWait:^{
   // do something
}];
[context.persistentStoreCoordinator unlock]

我不知道它为什么起作用,但我怀疑 NSManagedObjectContext 的错误。我希望这将有所帮助。

于 2014-07-26T07:00:09.270 回答
0

我在使用完整存储进行测试时得到了这个。因此,似乎任何类型的合并失败(在我的情况下,存储已满并且无法更新持久存储)都会产生这种情况。

于 2014-09-18T21:57:45.520 回答