Created
January 28, 2015 02:38
-
-
Save bradya/0f17bb779efd92c3f7b5 to your computer and use it in GitHub Desktop.
Core Data queue abstraction
This file contains hidden or 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
#pragma mark - Block Methods | |
/* | |
When we team switch, we want to completely stop in-progress data changes | |
E.g. if we're dumping the cache on Team A and you switch teams, we use | |
[SLKTeam currentTeam] throughout the app, and when that code executes, it'll | |
do stuff for the wrong team. | |
Core Data doesn't provide direct access to the MOC queues, so we implement | |
our own queues on top of the MOC queues which gives us the ability to | |
pause the queues, cancel operations, and generally ensure that operations | |
happen when we want them to, instead of when Core Data wants them to. | |
*/ | |
+ (void)performMainBlock:(void (^)())block | |
{ | |
[self performContextBlock:SLKContextTypeMain block:block]; | |
} | |
+ (void)performBackgroundBlock:(void (^)())block | |
{ | |
[self performContextBlock:SLKContextTypeBackground block:block]; | |
} | |
+ (void)performReadBlock:(void (^)())block | |
{ | |
[self performContextBlock:SLKContextTypeRead block:block]; | |
} | |
+ (void)performContextBlock:(SLKContextType)contextType block:(void (^)())block | |
{ | |
// Give up immediately if we don't have a block | |
if (!block) { | |
return; | |
} | |
// Get the context and queue for the specified context type | |
// This allows us to write this logic once | |
NSManagedObjectContext *context = [self contextForType:contextType]; | |
NSOperationQueue *queue = [self queueForType:contextType]; | |
// Adds the operation to the queue | |
[queue addOperationWithBlock:^{ | |
/* | |
We use a dispatch group to block the thread that the NSOperationQueue is | |
operating on, so operations are only fired off to the Core Data queues | |
one at a time. | |
This makes it so that if we pause the queue or cancel all operations, | |
the only block being executed in the MOC finishes, blocking the main thread | |
while we wait for it to complete (a necessary evil, for now) | |
*/ | |
__block dispatch_group_t group = dispatch_group_create(); | |
dispatch_group_enter(group); | |
// We want to use performBlock because it provides us with | |
// a free autoreleasepool and synchronizes changes better than performBlockAndWait | |
[context performBlock:^{ | |
block(); // Actually execute the logic here | |
dispatch_group_leave(group); // Release the group, which is blocking the calling thread | |
}]; | |
// Block the queue's thread until performBlock completes | |
dispatch_group_wait(group, DISPATCH_TIME_FOREVER); | |
}]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment