Search code examples
objective-ccocoacore-datansmanagedobjectcontext

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


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]);
        }
    }

Solution

  • 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];
    }