CoreData
Entity "A" has a one-to-many relationship to a collection of CoreData
Entries "B", using a Cascade delete rule.
In an iCloud
environment, while device 1 shows a detail view of one of the "B" entries, device 2 deletes the "A" entry.
When the NSPersistentStoreDidImportUbiquitousContentChangesNotification
notification is received in device 1, its App Delegate calls mergeChangesFromContextDidSaveNotification
and then broadcasts an internal notification which is captured by the view controller showing the details of entry "B" (the code uses performBlock
where 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 CoreData
object. 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.
mergeChangesFromContextDidSaveNotification
appears 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 stalenessInterval
of 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 null
entry "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?
ON DELETE CASCADE is fine, but only when the dependent rows are really a logical extension of the row being deleted. For example, it's OK for DELETE ORDERS to delete the associated ORDER_LINES because clearly you want to delete this order, which consists of a header and some lines.
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).
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