Changes saved from one NSManagedObjectContext doesn't reflect on main NSManagedObjectContext

mongeta picture mongeta · May 27, 2011 · Viewed 11k times · Source

I have a main NSManagedObjectContext that's created in the appDelegate.

Now, I'm using another NSManagedObjectContext for editing/adding new objects without affecting the main NSManagedObjectContext, until I save them.

When I save the second NSManagedObjectContext, the changes are not reflected in the main NSManagedObjectContext, yet if I open the .sqlite database from simulator, the changes have been saved correctly into the .sqlite database. It doesn't matter if I fetch the data again, or even if I create a third NSManagedObjectContext, I cannot see those changes from the second NSManagedObjectContext, despite the fact those changes do actually exist on disk at this point.

If I quit and re-open the app, all changes are there.

What can cause the main NSManagedObjectContext to not see the new changes present in the persistent store?

Before this approach, I was using a single NSManagedObjectContext and undoManager, but I wanted to change it to use two different NSManagedObjectContexts.

The second NSManagedObjectContext save:

    NSError* error = nil;

    if ([managedObjectContext hasChanges]) {
        NSLog(@"This new object has changes");
    }

    if (![managedObjectContext save:&error]) {
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
        if(detailedErrors != nil && [detailedErrors count] > 0) {
            for(NSError* detailedError in detailedErrors) {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
            }
        }
        else {
            NSLog(@"  %@", [error userInfo]);
        }
    }

Answer

octy picture octy · May 27, 2011

If you haven't already done so, I suggest reading the Apple documentation on Core Data : Change Management.

You need to notify the first context of the changes that were saved through the second context. When saving a context, it posts a NSManagedObjectContextDidSaveNotification. Register for that notification. In the handler method, merge into the first context the changes saved through the second context. For example:

// second managed object context save

// register for the notification
[[NSNotificationCenter defaultCenter] 
    addObserver:self 
       selector:@selector(handleDidSaveNotification:)
           name:NSManagedObjectContextDidSaveNotification 
         object:secondManagedObjectContext];

// rest of the code ommitted for clarity
if (![secondManagedObjectContext save:&error]) {
    // ...
}

// unregister from notification
[[NSNotificationCenter defaultCenter] 
    removeObserver:self 
              name:NSManagedObjectContextDidSaveNotification 
            object:secondManagedObjectContext];

Notification handler:

- (void)handleDidSaveNotification:(NSNotification *)note {
    [firstManagedObjectContext mergeChangesFromContextDidSaveNotification:note];
}