How to merge unsaved NSManagedObjectContext changes from one context to another?

756 views Asked by At

I have two NSManagedObjectContext's, one is used to write data from an api response in the background, and the other is to populate a NSFetchedResultsController as follows:

// moc used to fetch objects via NSFetchedResultsController:

    moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
            moc.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy


// moc used when writing data from an api response:

    backgroundMoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
            moc.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy

There are objects that are transiently stored in the background moc (without calling .save()), and I need to merge those changes to over to the main moc so that my NSFetchedResultsController has access to it.

I tried subscribing to NSManagedObjectContextDidSaveNotification, but that only gets hit if i call backgroundMoc.save(), which i am trying to avoid, since the objects in my backgroundMoc have unsaved changes.

What is the best way to do so?

2

There are 2 answers

0
Tom Harrington On

There's no built-in mechanism for this. When you have unsaved changes in one context, those changes only exist in that context. Other contexts can't see them, so they can't get the information they contain. If you don't want to save changes, your only option is to make the same changes again in the other context. That is, whatever you did in context A, do it again in context B so it has the same changes.

0
malhal On

Use NSPersistentContainer and set automaticallyMergesChangesFromParent on the viewContext which you should use for your fetch controller and then use a newBackgroundContext for your background work. When the background context saves, its persistent coordinator (which is also the parent of viewContext) notifies the viewContext which merges in the changes.

Note if you don't want all the background objects added to the view context then you can instead observe the notification and filter in the objects you require, for example ones that the current view controller is or should be showing. You'll probably need to observe in multiple places.

This is beyond the scope of this question but if your background context is in another process, e.g. an extension, then you can make use of persistent history to query for what the changes were and add those to the view context.