iPhone Coredata error (NSMergeConflict for NSManagedObject)

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}" );

Answers


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.

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();
    }
  } }

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
}()

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.


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
}()

Need Your Help

does ModelAndView from Spring MVC have an equivalent in Play framework

playframework java-ee-7

does ModelAndView have a direct equivalent in Play framework, and if not how could I recreate SpringMVC code in Play that uses this class, is their some simple code that could do it?

How to get nested asynchronous calls resolved before completion block

ios multithreading swift grand-central-dispatch dispatch-async

Here's the setup. I have a method that has a completion block in which I want to return a list of Items. These Items are fetched from an API. I'd like to have each of the fetches happen asynchronou...