Key data: Parental context and change propagation

I have the following Core Data settings in my application:

Persistent Store Coordinator ^ Background MOC (NSPrivateQueueConcurrencyType) ^ Main Queue MOC (NSMainQueueConcurrencyType) 

Here is the initialization code:

 _backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [_backgroundContext setPersistentStoreCoordinator:self.coordinator]; _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [_mainContext setParentContext:_backgroundContext]; 

I use background MOC to import large amounts of data. I also use it to perform complex fetch queries in the background, and then pass the identifiers of objects in the main queue to retrieve objects using these identifiers.

This works pretty well. However, I am not sure how to report the main MOC queue about changes made in the background of the MOC. I know that if I execute a select request in the main MOC queue, it will receive the changes, but this is not what I want.

Can I use the NSManagedObjectContextObjectsDidChangeNotification notification sent by the MOC background and call mergeChangesFromContextDidSaveNotification: in the main MOC queue? This should then trigger an NSManagedObjectContextObjectsDidChangeNotification notification of the main MOC queue. I listen to this notification in my controllers and look at userInfo to change and redisplay the data accordingly. I think you usually do it this way if you have one permanent store coordinator with two MOCs attached. But I'm not sure if this is the right way when you have child / parent contexts.

+6
source share
2 answers

I would say that listening to the NSManagedObjectContextObjectsDidChangeNotification notification is not the best solution.

How do I do it and it works. Here is the basic context creation:

 _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; _mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; _mainContext.persistentStoreCoordinator = _persistentStoreCoordinator; 

Here is the creation of the background context:

 _backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; _backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; _backgroundContext.parentContext = self.mainContext; 

Now the background context is intended only for writing (or reading) objects (it can be in the background thread). The main context is read-only from the main queue. Save in the background context should look like this:

 __block BOOL saved = [_backgroundContext save:error]; if (saved && _backgroundContext.parentContext) { [_backgroundContext.parentContext performBlockAndWait:^{ saved = [self.parentContext save:error]; }]; } 

This save method ensures that all changes are propagated in the main context. If you work a lot in many background threads, performBlockAndWait: method, which provides mutual exclusion in context.

If you want to be notified of changes to objects, you do not need to listen to the notification, you can simply set up NSFetchedResultsController and register as your delegate.

+3
source

If the primary MOC uses the closed parent MOC for asynchronous I / O, this is normal. However, you should not use this parent MOC for anything other than doing background work on behalf of the main MOC. There are many reasons for this (among them, performance and unpleasant problems associated with transient identifiers).

If you want to do a background update of the store, here is what I offer.

 PSC <--+-- PrivateMOC <---- MainMOC | +-- BackgroundPrivateMOC 

This allows you to use the background mode, which causes the least interruption of the main MOC, allowing you to share PSC caching.

Now for sharing data ...

MainMOC should listen and combine DidSave notifications from BackgroundPrivateMO.

BackgroundMOC can listen and combine DidSave notifications from PrivateMOC.

This allows the merge to use only persistent object identifiers and optimize performance.

+3
source

Source: https://habr.com/ru/post/956253/


All Articles