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.