iOS 5 introduced a new way to quickly fetch data on a background thread by initializing the MOC using NSPrivateQueueConcurrencyType
and then doing the fetch in performBlock:
One of the rules of thumb of Core Data has been that you can not share a managed object between threads/queues. Is it still the case with performBlock:
? Is the following:
[context performBlock:^{ // fetch request code NSArray *results = [context executeFetchRequest:request error:nil]; dispatch_async(dispatch_get_main_queue(), ^(void) { Class *firstObject = [results objectAtIndex:0]; // do something with firstObject }); }];
still unacceptable since I'm sharing my results array/objects between the bg queue and the main queue? Do I still need to use the managed object IDs to do that?
When you use NSPrivateQueueConcurrencyType
you need to do anything that touches that context or any object belonging to that context inside the -performBlock:
method.
Your code above is illegal since you're passing those objects back to the main queue. The new API helps you in solving this, though: You create one context that's associated with the main queue, i.e. with NSMainQueueConcurrencyType
:
// Assume we have these two context (They need to be set up. Assume they are.) NSManagedObjectContext *mainMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease]; NSManagedObjectContext *backgroundMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease]; // Now this can safely be called from ANY thread: [backgroundMOC performBlock:^{ NSArray *results = [backgroundMOC executeFetchRequest:request error:nil]; for (NSManagedObject *mo in results) { NSManagedObjectID *moid = [mo objectID]; [mainMOC performBlock:^{ NSManagedObject *mainMO = [mainMOC objectWithID:moid]; // Do stuff with 'mainMO'. Be careful NOT to use 'mo'. }]; } }];
This gets less confusing if you move the inner [mainMOC performBlock:]
call into its own method. You may also want to pass an array of object IDs back to the main thread's context in stead of executing a block for each object ID. It depends on your needs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With