The key here is not that line in the stack trace, it's the exception message:
*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xd0000000001c0000 ''
If Core Data complains that an object is inaccessible, that means it could not find the object in the persistent store. Let's look at why this happens in your code:
- You create an instance using
insertingContext
and save changes there and in the parent. At this point, your one object is in the persistent store file. - You fetch this instance using
acceesingContext
and make changes to it, but you do not save changes. At this point,acceesingContext
has in-memory, unsaved changes to the object you just fetched. - You fetch the object using
deletingContext
and delete it. Then you save changes indeletingContext
and in the parent. At this point, you have removed the object from the persistent store file. However, and this is crucial,acceesingContext
still has unsaved changes for that object. - You save changes on
acceesingContext
. SinceacceesingContext
has unsaved changes on the object you fetched, it tries to update that object. But that object doesn't exist in the persistent store, because you deleted it. SinceacceesingContext
can't update a nonexistent object, it throws an exception and the app crashes.
One thing to keep in mind when using nested managed object contexts is that saving changes only pushes changes in one direction-- toward the parent. If you have two sibling contexts (in this case acceesingContext
and deletingContext
), saving changes on one child does not automatically update the other.
Since this is obviously demo code (thanks, BTW, makes it easier to follow!) it's hard to be completely certain what you would need to do in your real app code. A typical approach is to listen for NSManagedObjectContextDidSaveNotification
and then use mergeChangesFromContextDidSaveNotification:
to apply changes from one context into another one. That way when one context deletes an object, you can update other contexts to reflect that fact. This makes it possible to keep multiple managed object contexts in sync with each other.