Skip to content

Instantly share code, notes, and snippets.

@mikeabdullah
Last active September 2, 2016 13:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeabdullah/faa6fd7a75c04e7f9f9c to your computer and use it in GitHub Desktop.
Save mikeabdullah/faa6fd7a75c04e7f9f9c to your computer and use it in GitHub Desktop.
Safer merge from saved context
- (void)mergeChangesFromSaveNotification:(NSNotification *)notification
intoContext:(NSManagedObjectContext *)context {
// NSManagedObjectContext's merge routine ignores updated objects which aren't
// currently faulted in. To force it to notify interested clients that such
// objects have been refreshed (e.g. NSFetchedResultsController) we need to
// force them to be faulted in ahead of the merge
NSSet *updated = [notification.userInfo objectForKey:NSUpdatedObjectsKey];
for (NSManagedObject *anObject in updated) {
// The objects can't be a fault. -existingObjectWithID:error: is a
// nice easy way to achieve that in a single swoop.
[context existingObjectWithID:anObject.objectID error:NULL];
}
[context mergeChangesFromContextDidSaveNotification:notification];
}
@tomandersen
Copy link

tomandersen commented Sep 2, 2016

// above code will fault with multithread debugging enabled, so collect Ids, then do a block.
// http://mikeabdullah.net/merging-saved-changes-betwe.html

- (void)mergeChangesFromSaveNotification:(NSNotification *)notification intoContext:(NSManagedObjectContext *)context {

    //Collect the objectIDs of the objects that changed
    NSMutableSet *updated = [NSMutableSet set];
    NSDictionary *userInfo = notification.userInfo;
    for (NSManagedObject *changedObject in userInfo[NSUpdatedObjectsKey]) {
        [updated addObject:changedObject.objectID];
    }

// NSManagedObjectContext's merge routine ignores updated objects which aren't
// currently faulted in. To force it to notify interested clients that such
// objects have been refreshed (e.g. NSFetchedResultsController) we need to
// force them to be faulted in ahead of the merge

     [context performBlock:^{
        for (NSManagedObjectID *anObjectID in updated) {
            // The objects can't be a fault. -existingObjectWithID:error: is a
            // nice easy way to achieve that in a single swoop.
            [context existingObjectWithID:anObjectID error:NULL];
        }

        [context mergeChangesFromContextDidSaveNotification:notification];
    }];
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment