I have an application using Core Data with the following, fairly standard, managed object context hierarchy:
Persistent Store Coordinator ↳ Save Context (Private Queue Concurrency Type) ↳ Main Context (Main Queue Concurrency Type) ↳ Private Context (Private Queue Concurrency Type) The merge policy for all managed object contexts is set to NSMergeByPropertyObjectTrumpMergePolicy
I am observing NSManagedObjectContextDidSaveNotification which will invoke the following function when the Private Context is saved and merge changes to the Main Context:
func contextDidSaveNotificationHandler(notification: NSNotification) { if let savedContext = notification.object as? NSManagedObjectContext { if savedContext == privateObjectContext { mainObjectContext.performBlock({ if let updatedObjects = notification.userInfo![NSUpdatedObjectsKey] as? Set<NSManagedObject> { // // fire faults on the updated objects // for obj in updatedObjects { mainObjectContext.objectWithID(obj.objectID).willAccessValueForKey(nil) } } mainObjectContext.mergeChangesFromContextDidSaveNotification(notification) }) } } } This is working most of the time but sometimes I am finding that changes to existing objects in the Private Context are not being merged into the Main Context. I can't figure out why -- the private context save is successful; the NSManagedObjectContextDidSaveNotification notification is being sent; the notification handler is being invoked; notification.userInfo?[NSUpdatedObjectsKey] contains the correctly updated objects; but at the end, the main context is not synchronized with the private context. (ie: the managed objects in the main context are not in sync with the values contained in notification.userInfo?[NSUpdatedObjectsKey]) If I kill the app and relaunch it, the contexts become synchronized again (after loading objects from the persistent store).
I have -com.apple.CoreData.ConcurrencyDebug 1 enabled in my launch arguments, and all Core Data multithreading rules are being followed. I can't see anything overtly wrong with my managed object context hierarchy or the merging function. What could possibly be causing this?
if savedContext == privateObjectContext {isprivateObjectContextthe parent of the main context or the sibling?mainObjectContext.objectWithID(_:)) before and after callingmainObjectContext.mergeChangesFromContextDidSaveNotification(notification). I'm also logging thenotification.userInfo?[NSUpdatedObjectsKey]values since those represent the state of the objects in the private context. And privateObjectContext is the sibling of the main context