Core Data and threads / Grand Central Dispatch Core Data and threads / Grand Central Dispatch multithreading multithreading

Core Data and threads / Grand Central Dispatch


Here's a good example for you to try. Feel free to come back if you have any questions:

self.mainThreadContext... // This is a reference to your main thread contextNSPersistentStoreCoordinator *mainThreadContextStoreCoordinator = [self.mainThreadContext persistentStoreCoordinator];dispatch_queue_t request_queue = dispatch_queue_create("com.yourapp.DescriptionOfMethod", NULL);dispatch_async(request_queue, ^{    // Create a new managed object context    // Set its persistent store coordinator    NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init];    [newMoc setPersistentStoreCoordinator:mainThreadContextStoreCoordinator]];    // Register for context save changes notification    NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];    [notify addObserver:self                selector:@selector(mergeChanges:)                    name:NSManagedObjectContextDidSaveNotification                  object:newMoc];    // Do the work    // Your method here    // Call save on context (this will send a save notification and call the method below)    BOOL success = [newMoc save:&error];    if (!success)        // Deal with error    [newMoc release];});dispatch_release(request_queue);

And in response to the context save notification:

- (void)mergeChanges:(NSNotification*)notification {    dispatch_async(dispatch_get_main_queue(), ^{        [self.mainThreadContext mergeChangesFromContextDidSaveNotification:notification waitUntilDone:YES];    });}

And don't forget to remove the observer from the notification center once you are done with the background thread context.

[[NSNotificationCenter defaultCenter] removeObserver:self];


Here's a snippet which covers GCD and UI in it's simplest terms. You can replace doWork with your code that does the CoreData work.

Concerning CD and thread safety, one of the nice parts about GCD is you can sections off areas of your application (subsystems) to synchronize and ensure they get executed on the same queue. You could execute all CoreData work on a queue named com.yourcompany.appname.dataaccess.

In the sample, there's a button which invokes the long running work, a status label, and I added a slider to show I can move the slider while the bg work is done.

// on click of button- (IBAction)doWork:(id)sender{    [[self feedbackLabel] setText:@"Working ..."];    [[self doWorkButton] setEnabled:NO];    // async queue for bg work    // main queue for updating ui on main thread    dispatch_queue_t queue = dispatch_queue_create("com.sample", 0);    dispatch_queue_t main = dispatch_get_main_queue();    //  do the long running work in bg async queue    // within that, call to update UI on main thread.    dispatch_async(queue,                    ^{                        [self performLongRunningWork];                        dispatch_async(main, ^{ [self workDone]; });                   });    // release queues created.    dispatch_release(queue);    }- (void)performLongRunningWork{    // simulate 5 seconds of work    // I added a slider to the form - I can slide it back and forth during the 5 sec.    sleep(5);}- (void)workDone{    [[self feedbackLabel] setText:@"Done ..."];    [[self doWorkButton] setEnabled:YES];}