Core Data’s NSPrivateQueueConcurrencyType and sharing objects between threads

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.

Leave a Comment