I have updated my app to support iOS 7 and have been faced with the problem that on one of screens in my [context save];
I get the following error:
NSCocoaErrorDomain Code=133020 "The operation couldn’t be completed. (Cocoa error 133020.)" UserInfo=0x1115a6d0 {conflictList=(
"NSMergeConflict (0x1115a670) for NSManagedObject (0xf25c850) with objectID '0xf25c070 <x-coredata://76AF57C8-F7FF-4880-B06B-63F8B780C96D/Screen/p7>' with oldVersion = 5 and newVersion = 6
and old object snapshot = {\n index = 3;\n message = \"<null>\";\n status = 0;\n} and new cached row = {\n index = 3;\n message = \"<null>\";\n status = 0;\n}"
On iOS6 this problem does not occur.
Update: Code for managedObjectContext
-(NSManagedObjectContext *)managedObjectContextForCurrentThread{
if ([NSThread isMainThread])
{
NSManagedObjectContext *parentContext = self.mainManagedObjectContext.parentContext;
[parentContext performBlockAndWait:^{
NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
[[self mainManagedObjectContext] setMergePolicy:mergePolicy];
}];
return self.mainManagedObjectContext;
}
else
{
NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];
NSManagedObjectContext *threadContext = [threadDict objectForKey:kCGMManagedObjectContextKey];
if (threadContext == nil)
{
threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSManagedObjectContext *parentContext = self.mainManagedObjectContext.parentContext;
[parentContext performBlockAndWait:^{
NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
[parentContext setMergePolicy:mergePolicy];
}];
[threadContext setParentContext:self.mainManagedObjectContext];
[threadDict setObject:threadContext forKey:kCGMManagedObjectContextKey];
}
return threadContext;
}
}
I didn't want to mask a potential problem by setting a merge policy without understanding what was causing the NSMergeConflict
first.
In my situation I had performed a NSBatchDeleteRequest
earlier on in my code. The NSBatchDeleteRequest
is performed directly on the persistent store coordinator so the ManagedObjectContext
was unaware of the deletions and still held references to deleted objects. When I later referenced one of these objects and tried to save the context, the NSMergeConflict
was thrown.
Calling reset()
on my moc
after performing the deletion fixed the issue.
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Tasks")
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
try managedContext.execute(batchDeleteRequest)
managedContext.reset()
I just spent two days debugging the exact same error. The difference between your app and mine is that mine only accesses core data from the main thread, so the merge error was even more puzzling.
In our case I narrowed it down to the fact that we had a unidirectional relationship - A has many Bs (modeled as an NSSet), but B doesn't know its A. We had a method that modified both an A and a B, and would cause a merge error when we went to save those changes. This code worked fine for a long time on both iOS 5 & 6, and only started to fail on iOS 7.
It's true that adding a merge policy will make the error go away, but it might also mask other errors. In our case we'd rather see those errors than risk having an inconsistent DB.
Changing the relationship to bidirectional made the error go away. The back links aren't necessary for our app, but they aren't hurting either. (And happily, changing this relationship was handled correctly as a lightweight migration - core data automatically filled in those back links for us.)
Using Xcode 6.3.2 with Apple Watchkit extension and I got this same error when trying to make multiple updates and saves. The setMergePolicy solved the problem and here are the swift code:
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
Make sure to put the above line before the context.save command.
I got similar error, and in my case, locking NSPersistentStoreCoordinator worked.
[context.persistentStoreCoordinator lock];
[context performBlockAndWait:^{
// do something
}];
[context.persistentStoreCoordinator unlock]
I don't know why it works, but I suspect NSManagedObjectContext's bug. I hope this will help.
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