Handling Core Data Store Change Notifications

The ubiquity container is emptied either by deleting all the contents from Mac File Manager or by calling the removeUbiquitousContentAndPersistentStoreAtURL API

Note that there may be other scenarios, like migration(migratePersistentStore:), store model upgrades and rebuilding the store(NSPersistentStoreRebuildFromUbiquitousContentOption) where this store switching also occurs.

Now it is important to remember that these notifications are always sent from a background thread and the managedObjectContext you want to save is almost always going to be your main context which should only be called from the main thread because managedObjectContext’s are not thread safe.

Another not so obvious thing to remember is that Core Data actually waits for the storesWillChange notification method to return before removing the current store and switching. This means that even though you need to call save on the main managedObjectContext using the main thread you need to do so synchronously to ensure Core Data does not remove the store before your main thread code gets run.

So we use the dispatch_sync to ensure the Core Data background thread waits until we have completed the save.

- (void)storesWillChange:(NSNotification*)n {
// Now save the context
// We MUST call this on the main thread because managedObjectContext
// is not thread safe and we MUST wait for it to complete to prevent
// Core Data from switching the store while we are doing a save
if ([NSThread isMainThread]) {
NSError *error;
if ([self.managedObjectContext hasChanges]) {
[self.managedObjectContext save:&amp;error];
}
[self.managedObjectContext reset];
} else {
dispatch_sync(dispatch_get_main_queue(), ^ {
NSError *error;
if ([self.managedObjectContext hasChanges]) {
[self.managedObjectContext save:&amp;error];
}
[self.managedObjectContext reset];
});
}
}