iPhone Coredata错误(NSManagedObject的NSMergeConflict)

21
有时我在相同的地方使用coredata时会出现这个错误,有时它正常,而在其他时候我就会遇到这个错误。这是什么意思?我找不到任何关于它的内容 :(

ps 对不起我的英文 :)

冲突列表 = ( "NSMergeConflict (0xd447640) for NSManagedObject (0xd41b370) with objectID '0xd41b500 ' with oldVersion = 4 and newVersion = 5 and old object snapshot = {\n album = \"{(\n)}\";\n audios = \"{(\n)}\";\n bdate = \"\";\n city = \"\";\n country = \"\";\n dialog = \"{(\n)}\";\n domain = \"white.smoke\";\n faculty = 0;\n facultyName = \"\";\n firstName = White;\n graduation = 0;\n homePhone = \"\";\n isFriend = 1;\n isMe = 0;\n lastName = Smoke;\n mobilePhone = \"\";\n nickName = \"\";\n online = 1;\n photo = \"\";\n photoBig = \"\";\n photoComments = \"{(\n)}\";\n photoMedium = \"\";\n photoRec = \"http://cs10609.vkontakte.ru/u79185807/e_8c949409.jpg\";\n photos = \"{(\n (entity: Photo; id: 0xd482c50 ; data: {\n aid = 121594781;\n album = nil;\n comments = \\"\\";\n commentsCount = 0;\n created = \\"2010-12-10 03:45:01 GMT\\";\n owner = \\"0xd41b500 \\";\n \\"owner_id\\" = 79185807;\n photosNumber = 0;\n pid = 196997145;\n src = \\"http://cs10609.vkontakte.ru/u79185807/121594781/m_\\";\n \\"src_big\\" = \\"http://cs10609.vkontakte.ru/u79185807/121594781/x_\\";\n \\"src_small\\" = \\"http://cs10609.vkontakte.ru/u79185807/121594781/s_\\";\n \\"src_xbig\\" = nil;\n \\"src_xxbig\\" = nil;\n wallRel = \\"0xd480840 \\";\n}),\n (entity: Photo; id: 0xd431570 ; data: {\n aid = 121594781;\n album = nil;\n comments = \\"\\";\n commentsCount = 0;\n created = \\"2010-12-10 03:43:01 GMT\\";\n owner = \\"0xd41b500 \\";\n \\"owner_id\\" = 79185807;\n photosNumber = 0;\n pid = 196997029;\n src = \\"http://cs10609.vkontakte.ru/u79185807/121594781/m_\\";\n \\"src_big\\" = \\"http://cs10609.vkontakte.ru/u79185807/121594781/x_\\";\n \\"src_small\\" = \\"http://cs10609.vkontakte.ru/u79185807/121594781/s_\\";\n \\"src_xbig\\" = nil;\n \\"src_xxbig\\" = nil;\n wallRel = \\"0xd42d500 \\";\n})\n)}\";\n rate = \"-19\";\n sex = 0;\n statuses = \"{(\n)}\";\n timezone = 0;\n uid = 79185807;\n university = 0;\n universityName = \"\";\n videos = \"{(\n)}\";\n wall = \"{(\n)}\";\n wallPostsCount = 0;\n wallReplies = \"{(\n (entity: WallReply; id: 0xd448270 ; data: )\n)}\";\n wallSender = \"{(\n)}\";\n} and new cached row = {\n bdate = \"\";\n city = \"\";\n country = \"

5个回答

36

当你的数据库从两个不同的地方进行更改并保存后,可能会出现合并冲突。在某些情况下,更改可能会影响相同的对象或属性,并且Core Data不会自动覆盖它们,因为那样可能会破坏有价值的数据。

有几个选项:

  • 当你遇到合并冲突时,请遍历相关信息,并按照你的应用程序的需要手动解决任何冲突。
  • 设置托管对象上下文的合并策略,以自动解决某些类型的冲突。一些合并策略是部分破坏性的,一些则非常具有破坏性 - 哪种策略适合取决于你的应用程序和被保存的数据的重要性。
  • 使用mergeChangesFromContextDidSaveNotification:快速而紧密地将更改集成到尚未保存的托管对象上下文中。请注意,这仍可能需要一定程度的冲突解决,但应该有助于将其最小化。

好的,我想我找到了导致这个错误的原因。在一些方法中,我正在使用for(id * in *)将json数据插入到coredata中,我在其中设置了很多属性和对象关系。只有在这之后,我才保存上下文。现在我将[context save:&error]插入到“for”结尾处,我就再也没有看到错误了 :) - ruffnecktsk
1
如果你在每次循环迭代后保存上下文,那听起来像是一个相当大的打击。你可能需要花时间调查是否同时发生了其他更改,因为你不可能在同一上下文中连续进行多个更改而出现合并冲突。 - Justin Spahr-Summers
3
我遇到了这样一个问题,那就是相同的对象存储在两个不同的MOC中,这阻止了CD的保存。只需要添加一个mergePolicy就解决了我的保存错误。谢谢! - Brian
请确保在两个上下文中都设置了mergePolicy。 - ma11hew28
嗨,@JustinSpahr-Summers,你能看一下这个问题吗?http://stackoverflow.com/questions/19443853/nsmergeconflict-for-nsmanagedobject-with-single-managedobjectcontext - Ranjit

15

简而言之 - 启用合并策略,将以下内容添加到您的 MOC 设置中:

objective-C

[_managedObjectContext setMergePolicy:[[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType]];

迅速

 lazy var managedObjectContext: NSManagedObjectContext? = {

    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil {
        return nil
    }
    var managedObjectContext = NSManagedObjectContext()
    managedObjectContext.persistentStoreCoordinator = coordinator

    //add this line 
    managedObjectContext.mergePolicy = NSMergePolicy(mergeType: NSMergePolicyType.MergeByPropertyObjectTrumpMergePolicyType);

    return managedObjectContext
}()

8
我在保存上下文时遇到了相同的合并冲突,请参阅苹果文档此处。我通过使用NSMergePolicy来解决冲突。
- (BOOL)resolveConflicts:(NSArray *)list error:(NSError **)error

在创建NSMergePolicy对象时,将policyType设置为NSOverwriteMergePolicyType

NSOverwriteMergePolicyType:指定一个策略,用于覆盖冲突中更改对象的持久存储状态。

`

if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {

  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

  NSArray * conflictListArray = (NSArray*)[[error userInfo] objectForKey:@"conflictList"];
  NSLog(@"conflict array: %@",conflictListArray);
  NSError * conflictFixError = nil;

  if ([conflictListArray count] > 0) {

    NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSOverwriteMergePolicyType];

    if (![mergePolicy resolveConflicts:conflictListArray error:&conflictFixError]) {
      NSLog(@"Unresolved conflict error %@, %@", conflictFixError, [conflictFixError userInfo]);
      NSLog(@"abort");
      abort();
    }
  } }

5

Swift 4

private(set) lazy var mainContext: NSManagedObjectContext = {

    let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    context.parent = privateContext

    context.mergePolicy = NSMergePolicy(merge: .overwriteMergePolicyType)

    // Or we can use Trumping 
    // .mergeByPropertyObjectTrumpMergePolicyType
    // .mergeByPropertyStoreTrumpMergePolicyType

    // Rolling back is another option
    // .rollbackMergePolicyType

    return context
}()

2

这是半解决的问题,也许 :) 例如,您有以下代码,在N个对象中存在(每个对象都在单独的线程中,并且在同一时间创建(+-10ms)):

[coreObject addLinkedObject:linkedObject1];

在上下文中处理例程的时间大约为70毫秒。如果您只设置NSMergePolicy(例如):NSOverwriteMergePolicy,则仅会有最后一个对象添加链接,因为每个上下文都是持久存储的内存快照。因此,每个快照都是在常规对象创建的时间时刻创建的。70毫秒的处理时间滞后导致在保存它时coreObject的信息过时。换句话说,您将只有一个保存的链接或合并错误。当然,您可以订阅NSManagedObjectContextObjectsDidChangeNotification,但在这种情况下,您将拥有N!订阅关系,或者您可以以星形方式跨主线程订阅主要上下文,但有时无法正常工作(我正在使用MagicalRecord,版权所有2011年Magical Panda Software LLC)。我的解决方案是在保存之前重新读取关键的coreObject,并使用适当的合并策略:

 @synchronized (self) {
        if ([context hasChanges]) {
            if (needRefresh) {
                [context refreshObject:coreObject mergeChanges:NO];
                [coreObject addLinkedObject:linkedObject1];
            }
            NSError *err = nil;
            [context save:&err];
            if (err) {
                NSLog(@"Error Saving Linked Object: %@", [err userInfo]);
                [context rollback];
            }
        }
}

在这种情况下,风险最小化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接