Skip to content

Instantly share code, notes, and snippets.

@jbrjake
Created August 19, 2015 21:42
Show Gist options
  • Save jbrjake/24cded8fb16bb85efefe to your computer and use it in GitHub Desktop.
Save jbrjake/24cded8fb16bb85efefe to your computer and use it in GitHub Desktop.
The fun of Core Data concurrency
#import "ViewController.h"
#import <CoreData/CoreData.h>
#import "AppDelegate.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
NSManagedObject *foo = [[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"Foo" inManagedObjectContext:delegate.managedObjectContext] insertIntoManagedObjectContext:delegate.managedObjectContext];
[delegate.managedObjectContext save:nil];
[self updateFoo:foo.objectID];
}
// Updates foo so foo.qux == @"bar"
- (void)updateFoo:(NSManagedObjectID*)fooID {
// Create a private context to do work, as a child of the main context
// Note: the main context has been initialized with the main queue concurrency type
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
moc.parentContext = delegate.managedObjectContext;
/* Because we're using a MOC with its own private queue, we want to perform operations safely within that queue.
Which means we do those operations inside a block dispatched asychronously to the MOC's queue.
However, we don't want this method to return until foo has actually been updated...
Since we're operating on the context asynchronously, we can use a semaphore to block until it's done.
Per Apple's man page on dispatch_semaphore:
If the count parameter is equal to zero, then the semaphore is useful for synchronizing completion of
work. For example:
sema = dispatch_semaphore_create(0);
dispatch_async(queue, ^{
foo();
dispatch_semaphore_signal(sema);
});
bar();
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
*/
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[moc performBlock:^{
// Reconstitute foo from the persistent store
NSManagedObject *foo = [moc objectWithID:fooID];
// Actually update foo, to set its "qux" key's value to "bar"
[foo setValue:@"bar" forKey:@"qux"];
// We're done, so signal that this asynchronous block has completed
dispatch_semaphore_signal(semaphore);
}];
// If we get past the next line, the semaphore's been signaled from inside the context block
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment