If you are executing the NSOperation
concurrently, as your code indicates, you basically have no control which thread is used to execute the operation's start
method.
This complicates the latter.
Thus, I would suggest to create your backgroundContext using a NSPrivateQueueConcurrencyType
concurrency type, like so:
self.backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
(see NSManagedObjectContext: Concurrency).
This enables you to execute any code within the managed object context's appropriate "execution context":
Invoking it asynchronously:
[self.backgroundContext performBlock: ^{
// executing on the background context's private queue
...
}];
Invoking it synchronously:
[self.backgroundContext performBlockAndWait: ^{
// executing on the background context's private queue
...
}];
Then, in your start
method you invoke the "snap shotter" as follows:
...
[snapshotter startWithQueue:dispatch_get_global_queue(0, 0)
completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
[self.backgroundContext performBlock:^{
// executing on the background context's private queue
...
self.snapshot = snapshot;
// here you likely need to orderly "terminate" the operation queue:
dispatch_async(_syncQueue, ^{
// set operation result:
if (error) { ... }
[self terminate];
}
}];
}];
Side note:
The implementation of terminate
may look as follows:
- (void) terminate {
self.isExecuting = NO;
self.isFinished = YES;
completion_block_t completionHandler = _completionHandler;
_completionHandler = nil;
id result = _result;
_self = nil;
if (completionHandler) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
completionHandler(result);
});
}
}