Core Data separate managed object context sharing same persistent store does not see changes

I am really baffled today by what I discovered.

I thought as long as all context are using the same Core Data persistent store, any changes in one context should appear in the other context after saving the context.

E.g. In view controller A I have 1 context (context A), in view controller B, I have another context (context B). Now both context A and context B point to the same persistent store.

In context A, I fetched a managed object from the persistent store, updated a property of the managed object, then I save the changes back to the persistent store with managedObjectContext save operation.

Now I open my second view controller and perform a fetch request from the same persistent store but my second view controller does not see the updated property change, until I restart the simulator.

The really strange thing is, if it's the first time I insert a new managed object into the persistent store, controller B will see the changes but subsequent changes are not shown.

I have already fixed this problem after a long battle, I just want to know why having two separate context (both on main thread of course) sharing the same persistent store does not see the changes until simulator restart.

For those who want to know how I fixed it, in my base view controller which controller A and B both inherit from, instead of alloc-initing a new context (a hence why controller A and B have two separate contexts), I told the base view controller to reference the context in the app delegate (as a result, controller A and B now point to the same context).

Here's a diagram explaining what I am seeing:

The resulting value fetched in second view controller is the old value.

If I commit some data to the persistent store, it should become permanent and accessible ANYWHERE as long as I am fetching from that same persistent store, unless I am misunderstanding that managedObjectContext save: doesn't actually make the changes to persistent store immediately until the app results.

Answers


Zhang,

without details it's difficult to figure out the problem.

A simple suggestion is to verify if you merge changes between the two different context within your app. In other words, you need to verify the main context merges changes that come from the other one. This could simple achieved like the following.

Register for this notification where, for example, in your AppDelegate or you are creating the Core Data stack.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];

Implement the contextChanged: method to merge changes.

- (void)contextChanged:(NSNotification*)notification
{
    if ([notification object] == [self managedObjectContext])
        return;

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
        return;
    }

    [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}

For further info see Marcus Zarra tutorial.

In addition, if you use tables in combination with NSFetchedResultsController remember to implement delegate's methods. For info see NSFetchedResultsControllerDelegate class.

Hope that helps.


Need Your Help

How does the size of a pointer change when it is pointing at a single character and when at a dynamically declared array of long integers? C code

c

I know that an array declaration results in a block of memory being reserved, but with an array represented by a pointer this does not. As it contains the address of the first element of the array...

iPad\iPhone application structure

iphone ipad ios itunes universal

I am going to build an iOS application that will have different iPad\iPhone views, but will share some business logic. I want to develop the application in different XCode projects, not in a univer...