Created
August 19, 2015 21:42
-
-
Save jbrjake/24cded8fb16bb85efefe to your computer and use it in GitHub Desktop.
The fun of Core Data concurrency
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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