I'm using CoreData with iCloud to sync data between devices.
After every iCloud import (observing NSPersistentStoreDidImportUbiquitousContentChangesNotification
), I run a simple de-duplication algorithm to find and delete duplicated data.
After saving the changes I see warnings in the console from CoreData that all properties and relationships of a specific entity instance (which was deleted by the de-dupe algorithm) are replaced with nil/0.
CoreData: warning: An NSManagedObjectContext delegate overrode fault handling behavior to silently delete the object with ID '0xd000000000040006 <x-coredata://ADDDABCD-4891-4DCF-B55B-53AA64D11922/<ENTITY_NAME>/p1>' and substitute nil/0 for all property values instead of throwing.
The problem is that one relationship in this entity is not-optional which produces errors the next time iCloud wants to import those changes on other devices.
-[_PFUbiquityRecordsImporter operation:failedWithError:](979): CoreData: Ubiquity: Import operation encountered had trouble importing log file, Error Domain=NSCocoaErrorDomain Code=134302 "The operation couldn’t be completed. (Cocoa error 134302.)"
[...], an error occurred saving changes to the persistent store mutated during the import process. [...]
"The operation couldn’t be completed. (Cocoa error 1560.)"} User Info: { [...]
NSValidationErrorObject=<NSManagedObject: 0x1742c7bd0> (entity: <ENTITY_NAME>; [...]
{NSValidationErrorKey=<NON-OPTIONAL_RELATIONSHIP_NAME> [...]
"Error encountered while importing transaction log at URL: ...
How can I avoid that all properties are set to nil/0?
How I solved it.
My biggest mistake was how I handled the NSPersistentStoreDidImportUbiquitousContentChangesNotification
notification.
I only merged the changes in my "main" context (used in the main thread). But I forgot to merge the changes into my second "root" context (of type NSPrivateQueueConcurrencyType
) as well which I use to save the context into the persistent store and is the parent of the "main" context.
Without knowing the internals, I suspect that because my "root" context don't know about the ubiquitous content changes, the next time I save changes the resulting transaction logs (written to iCloud) were inconcistent. Now I merge the change notification into my "root" and "main" context and things start to work better.