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.
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...
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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With