Create / fetch entity magic record in a separate thread

I have an NSOperations group that should create and retrieve objects while in a queue.

  • When creating entities in NSOperations, can I just create a default context, or since I'm in a new thread not in the main thread, is this not allowed / not recommended? If I create a new object in this thread, what is the best way to combine it back into the default context, then (and not save to the repository)?

  • When collecting data in these streams, I need to extract and then update the data in this object. I do not understand how to do this, and then merges with the default context.

Or is it really not important which thread you extract / create only when you save?

I am talking about the default context above because I have NSFetchedResultsControllers that tracks the default context for updates and inserts. My solution is currently working, doing all this in the main thread, but the application starts to scan with the amount of data that is now passing through it.

I also have class control (via KVO) of the operation queue account. As soon as it reaches zero, I will procure salvation. I would prefer to save only after all of the above NSOperations are completed, as of now. Thanks for the help.

+4
source share
1 answer

For now, ignore MagicalRecord. To work with master data across multiple threads, you need to know a few things.

  • Do not skip NSManagedObject between threads. Instead, go to the NSManagedObjectID for the object you want and retrieve it in the background thread.
  • Responsibly create an NSManagedObjectContext . That means you should know what initWithConcurrencyType: means. We will consider this.

Main theme

Your main NSManagedObjectContext should be built with the concurrency type NSMainQueueConcurrencyType . This will allow you to use the queued contexts for sequential operations. Each time a background thread interacts with the main context, you must do the work using performBlock or performBlockAndWait .

 - (NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext != nil) { return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } 

Background theme

Whenever you do work in the background thread, you need to expand a new context. You should not share contexts between threads. Pass the link to your main thread context into your operation and create a background context after your operation starts. This will ensure that it builds on the thread where you will do the work.

 - (NSManagedObjectContext *)newBackgroundManagedObjectContext { // Create new context with private concurrency type NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [newContext setParentContext:self.mainContext]; // Optimization [newContext setUndoManager:nil]; return newContext; } 

Think of this background context as scratching. Whatever you do, they will remain there until you save. As you set parentContext, saving in the background context will merge the changes into your main context. This will update the NSFetchedResultsController , but the data has not yet been saved since you did not invoke the save. In your KVO queue, you can invoke a save in the main context by queuing a save block.

 [self performBlock:^{ NSError *error; [self save:&error]; if (error) { // handle errors } }]; 
+8
source

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


All Articles