Adding to a UIManagedDocument from a GCD background queue?

I create and add several managed objects to Core Data from the background queue. I realized that I could not access the context from the background thread, so I used executeBlock to schedule the addition of Core Data back to the same queue in which the context was created. This works great ...

My question during testing, I noticed that by removing [moc performBlock:^{ ... }]; , the application still works as expected (maybe even fractions of a second faster) Do I need to performBlock ? I would suggest that I do this and it just works (for now :) in non-streaming mode, I just wanted to check that my understanding was not a drawback.

 dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); dispatch_async(backgroundQueue, ^{ // GET DATA // PROCESS DATA NSManagedObjectContext *context = [[self managedDocument] managedObjectContext]; [moc performBlock:^{ // ADD TO CORE DATA [Core createRodInContext:context withDictionary:fuelRodDictionary]; }]; }); 

EDIT: Added implementation for createRodInContext ...

 + (Rod *)createRodInContext:(NSManagedObjectContext *)context withDictionary:(NSDictionary *)dictionary { // CREATE Rod *rod = [NSEntityDescription insertNewObjectForEntityForName:@"Rod" inManagedObjectContext:context]; // POPULATE [neo setDataCode:[dictionary objectForKey:@"dataCode"]]; [neo setDataName:[dictionary objectForKey:@"dataName"]]; [neo setDataReference:[dictionary objectForKey:@"dataReference"]]; ... return rod; } 
+4
source share
1 answer

In the background thread, you should use [moc performBlock:^{ ... }] to insert (and populate) the managed entity in the context of the main managed entity.

performBlock means that you are using the context of the managed entity (which was created in the main thread) also in another thread (which is associated with the background queue).

This may happen by accident, but as soon as the main thread accesses the MOC at the same moment as your background thread, the results are unpredictable because (as you said) the MOC is not thread safe.

See also Concurrency Support for managed entity contexts in the master data release notes for OS X v10.7 and iOS 5.0:

Confinement (NSConfinementConcurrencyType).

This is the default value. You promise that the context will not be used by any thread except the one on which you created it.

But also for other types of concurrency (private queue, main queue) you always need to use performBlock (or performBlockAndWait ) if your code is no longer running in the queue associated with the MOC.

+5
source

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


All Articles