4
votes

I've setup 2 NSManagedContext in a child-parent context in Core Data.

    _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_mainContext setParentContext:_parentContext];
    [_mainContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

    _importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_importContext setParentContext:_mainContext];
    [_importContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

What happens if I execute the following in order ("fetch" meaning NSFetchRequest):

  1. Fetch Managed object A in mainContext.
  2. Fetch Managed object A in importContext.
  3. Update object A in mainContext.
  4. Fetch Managed object A in importContext.

importContext (child) -> mainContext (parent) -> Persist Store Coordinator

My question is, at step 4, will the object that was fetched in the importContext have the updated changes I made at step 3 in the mainContext? Reading articles on the web seem to indicate that changes made in a parentContext are not propagated down to child context if the child context has already fetched the data (because contexts are cached?)

2

2 Answers

4
votes

Changes from a child context are propagated to the parent when the child is saved, not during fetching. Changes do not move in the other direction.

In your scenario...

Fetch Managed object A in mainContext.

mainContext will execute a fetch request against it's NSPersistentStoreCoordinator. The coordinator will locate the store that should service the request and give it the fetch. The persistent store will return a result, and depending on the store keep an in-memory copy of the row data. mainContext will now have an in-memory copy of this object (but not necessarily any of it's property values).

Fetch Managed object A in importContext.

importContext has no in-memory reference to this object, so it will pass the fetch to it's parent, mainContext. mainContext will pass back the reference to it's in-memory object A. If mainContext did not previously fetch the object, or if it was turned into a fault, mainContext would fetch all the way to the persistent store. Fetches and objectWithID: only go as many levels as they need to.

Update object A in mainContext.

The in-memory object A in mainContext is changed.

Fetch Managed object A in importContext.

The in-memory object A in importContext is returned. The changes made in mainContext will not be present in this object.

It's important to remember that when a context is created it's a "snapshot" of the state of it's parent. Subsequent changes to the parent will not be visible in the child unless the child is somehow invalidated (i.e. faulted or discarded).

You can see how changes propogate in this animation.

0
votes

What do you mean by "fetched"? A fetched results controller?

From my perspective, the answer to your question is a general "yes". Assuming a shared parent context of some kind, two contexts will get the newest object, if one context saves with a modified object, and the other context does something to load it again, for example, uses the objectID and - objectWithID: on the other context, to reload it.