iPhone Coredata error (NSMergeConflict for NSManagedObject)
Asked Answered
R

5

21

Sometimes i have this error with coredata in the same place. Sometimes its ok, and in other time i have this error. What does it mean? I can't find anything about it :(

ps sorry for my english :)

conflictList = ( "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 = \"\";\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 photoMedium = \"\";\n photoRec = \"http://cs10609.vkontakte.ru/u79185807/e_8c949409.jpg\";\n rate = \"-19\";\n sex = 0;\n timezone = 0;\n uid = 79185807;\n university = 0;\n universityName = \"\";\n wallPostsCount = 0;\n}" );

Rockie answered 10/12, 2010 at 5:19 Comment(0)
T
36

A merge conflict sometimes results when your database gets changed from two different places, then saved from two different places; in certain cases, the changes might affect the same objects or properties, and Core Data doesn't automatically overwrite them, as that might destroy valuable data.

There are a few options:

  • When you get a merge conflict, iterate through its information, and manually resolve any conflicts according to the needs of your application.
  • Set the merge policy of the managed object context(s) to one that will automatically resolve certain kinds of conflicts. Some merge policies are partially destructive, some are very destructive – which one is right really depends on your application and the importance of the data being saved.
  • Use mergeChangesFromContextDidSaveNotification: to quickly and closely integrate changes into managed object contexts that haven't been saved yet. Note that this may still require some level of conflict resolution, but should help minimize the severity.
Timaru answered 10/12, 2010 at 6:7 Comment(5)
Ok, i think i found what cause this error. In some methods i'm inserting json data to coredata using for (id * in *), where i'm setting a lot of attributes and relationships to objects. and only after that i'm saving context. Now i inserted [context save:&error] to the end of "for" and i don't see no more errors :)Rockie
That sounds like quite a hit, if you're saving the context after each loop iteration. You may want to spend time investigating whether other changes are occurring simultaneously, because you can't be getting merge conflicts for multiple consecutive changes in the same context.Timaru
I was having this problem with objects that were identical, but living in two different MOCs and it prevented CD from saving. Just adding a mergePolicy fixed my save errors. Thanks!Transversal
Make sure you set the mergePolicy on both contexts.Dip
Hi, @JustinSpahr-Summers, can you please have a look at this #19444353Mercury
I
16

In short - enable Merge Policy add this to your MOC setup:

objective-C

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

Swift

 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
}()
Immerse answered 27/4, 2015 at 21:20 Comment(0)
S
8

I got the same merge conflict, while saving the context. see apple doc here

I resolved the conflicts by using NSMergePolicy

- (BOOL)resolveConflicts:(NSArray *)list error:(NSError **)error

set policyType to NSOverwriteMergePolicyType while creating the NSMergePolicy object

NSOverwriteMergePolicyType: Specifies a policy that overwrites state in the persistent store for the changed objects in conflict.

`

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();
    }
  } }
Sanitation answered 30/1, 2014 at 10:3 Comment(0)
S
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
}()
Simulant answered 30/8, 2018 at 11:20 Comment(0)
C
2

It's semisolving, perhaps :) For example, you have following code, that exists in N objects (each one of them are in separate thread and are created in same time (+-10ms)):

[coreObject addLinkedObject:linkedObject1];

Time for processing routine in context is approx 70ms. if you just set NSMergePolicy to (for example): NSOverwriteMergePolicy, you will have Last-In-Changes: only last object will add link, because each context are snapshot-in-memory of persistent store. Thus each snapshot are created in time moment of routine object creation. 70ms processing time lag cause that information of coreObject is too old, when you save it. In other words you will have only one saved link or Merging error. Of course, you can subscribe on NSManagedObjectContextObjectsDidChangeNotification but in this case you'll have N! subscribed relations or you can subscribe in star manner cross main context in main thread, but sometimes it didn't work (I'm using MagicalRecord, Copyright 2011 Magical Panda Software LLC.). My solution is to re-read critical coreObject just before save it as well as using suitable merge policy:

 @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];
            }
        }
}

In this case risk is minimal.

Cacie answered 2/7, 2012 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.