CoreDataEntity “A” has a one-to-many relationship to a collection of
CoreDataEntries “B”, using a Cascade delete rule.
iCloudenvironment, while device 1 shows a detail view of one of the “B” entries, device 2 deletes the “A” entry.
NSPersistentStoreDidImportUbiquitousContentChangesNotificationnotification is received in device 1, its App Delegate calls
mergeChangesFromContextDidSaveNotificationand then broadcasts an internal notification which is captured by the view controller showing the details of entry “B” (the code uses
performBlockwhere it should).
However, although entry “A” is indeed nullified when the detail view controller receives the internal notification, entry “B” still exists as a valid
CoreDataobject. It seems that the Cascade rule hasn’t completed its operation yet. Therefore the view controller in device 1 isn’t aware of the delete, which may lead to unexpected results.
mergeChangesFromContextDidSaveNotificationappears to return prematurely, when the base data has been merged but the Cascade rule hasn’t completed yet.
I tried to refresh entry “B” when the notification arrives while temporarily setting the
stalenessIntervalof the managed object context to zero so a cached object won’t be used, but I still get a valid entry “B” from the store.
Checking for a
nullentry “A” at this point is not an option, because the situation is somewhat more complex than what I described here and a null entry “A” can be valid in some cases.
I tried to introduce a delay after merging the changes and before sending the internal notification to the view controllers. I found out that a 2-second delay doesn’t help, but a 10-second delay works.
But I don’t want to rely on this delay. This is a test environment without much data, and I don’t know what will happen in a production environment. Relying on an experimental delay doesn’t seem the right thing to do.
Is there a right thing? Or am I doing something wrong to begin with?
From experience, listening to notifications other than
NSManagedObjectContextDidSaveNotification is a big mess and can lead to relying on properties not yet updated. The detail view controller should listen to
NSManagedObjectContextDidSaveNotification notifications, which are thrown after cascade is applied. You can then check by several means if the current object is valid or not (you can check to see if the current object’s managed object context is
nil or you can perform a fetch and see if the object exists in the store).