iOS7 NSMergeConflict on Single Thread Save

Am having problems with a simple data save on a single threaded app after two rows have been re-ordered.

I’ve managed to simplify the coding to reproduce the error and would appreciate a second opinion with someone else trying this out.

  • CFBundleShortVersionString in info.plist must be higher than 1.0
  • Core Data change property from Integer 16 to Integer 32
  • Trying to get network error alert to show on iPhone app?
  • NSXMLParser stops parsing after encountering special character
  • Encrypt iOS and Decrypt Node.js AES
  • How do you trigger a block after a delay, like -performSelector:withObject:afterDelay:?
  • This is a sanity check as I’m suspicious of a core-data issue introduced with iOS 7 as this worked ok in iOS 6.

    Firstly, start a new core data project and create this model…

    simple core data model

    Attribute ‘current’ is an optional boolean. The one-to-many relationship is an ordered relationship, creating an NSOrderedDataset.

    Now add a couple of buttons to the app; the first to create the data (a project and two associated ‘drawings’) and the second to swap the two drawings, then set a property within the first drawing.

    Here’s the code…

    -(IBAction)onTestButton:(id)sender
    {
        id delegate = [[UIApplication sharedApplication]delegate];
        NSManagedObjectContext *managedObjectContext = [delegate managedObjectContext];
    
        self.project = [NSEntityDescription insertNewObjectForEntityForName:@"Project" inManagedObjectContext:managedObjectContext];
        Drawing *drawing1 = [NSEntityDescription insertNewObjectForEntityForName:@"Drawing" inManagedObjectContext:managedObjectContext];
        Drawing *drawing2 = [NSEntityDescription insertNewObjectForEntityForName:@"Drawing" inManagedObjectContext:managedObjectContext];
    
        NSMutableOrderedSet* tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.project.drawings];
        [tempSet addObject:drawing1];
        [tempSet addObject:drawing2];
        self.project.drawings = tempSet;
    
        [self save];
    }
    
    -(IBAction)onTestButton2:(id)sender
    {
        NSMutableOrderedSet *exchange = [self.project mutableOrderedSetValueForKey:@"drawings"];
        [exchange exchangeObjectAtIndex:0 withObjectAtIndex:1];
        self.project.drawings = exchange;
    
        [self save];
    
        Drawing *drawing = [self.project.drawings objectAtIndex:0];
    
        BOOL current = [drawing.current boolValue];
        drawing.current = [NSNumber numberWithBool:!current];
    
        [self save];
    }
    
    -(void)save
    {
        id delegate = [[UIApplication sharedApplication]delegate];
        NSManagedObjectContext *managedObjectContext = [delegate managedObjectContext];
        NSError *error = nil;
    
        if( ![managedObjectContext save:&error] )
        {
            NSLog(@"%@ Save: Unresolved Error on Save %@", error, [error userInfo] );
            abort();
        }
    }
    

    Now, test by pressing the first test button. This sets up the data.

    Then press the second test button….all OK!!!

    Now press the second test button again and BANG. You ‘should get a NSMergeConflict error similar to this….

    Save: Unresolved Error on Save {
    conflictList = (
    “NSMergeConflict (0x8a7d0b0) for NSManagedObject (0x8bedfa0) with objectID ‘0x8bd9340
    ‘ with
    oldVersion = 1 and newVersion = 2 and old object snapshot = {\n
    current = \”\”;\n project = \”0x8bc3f50
    \”;\n}
    and new cached row = {\n current = \”\”;\n project =
    \”0x8aa88c0
    \”;\n}”
    );

    I notice from the error that my Project object has changed. However, this is a single thread app using the main app context.

    I’ve spent far too long on this and would appreciate someone else passing comment as to where the issue is. Is this a core-data bug, or am I being a right ‘fool’?

    Many thanks

    /Fitto

    Solutions Collect From Internet About “iOS7 NSMergeConflict on Single Thread Save”

    I had similar issues an found a workaround here:

    http://prod.lists.apple.com/archives/cocoa-dev/2013/Oct/msg00657.html

    In short – add this to your MOC setup:

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

    This affects OS X 10.9 Mavericks as well when using NSSQLStoreType. I could not repeat the Merge error using NSXMLStoreType.

    For Swift 2.x

    managedObjectContext.mergePolicy = NSMergePolicy(mergeType: .MergeByPropertyObjectTrumpMergePolicyType)