I want to wrap an async API that look like this:
[someObject completeTaskWithCompletionHandler:^(NSString *result) {
}];
into a synchronous method that I can call like this:
NSString *result = [someObject completeTaskSynchronously];
How do I do this? I did some doc reading and internet search, and attempt to use "dispatch_semaphore" to do try to achieve it like so:
-(NSString *) completeTaskSynchronously {
__block NSString *returnResult;
self.semaphore = dispatch_semaphore_create(0);
[self completeTaskWithCompletionHandler:^(NSString *result) {
resultResult = result;
dispatch_semaphore_signal(self.semaphore);
}];
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
return resultResult;
}
But this doesn't seem to work, it basically just halt at dispatch_semaphore_wait. Execution never reaches inside block that do the _signal. Anyone has code example on how to do this? I suspect that the block has to be on a different thread other the main thread? Also, assume I don't have access to the source code behind the async method.
dispatch_semaphore_wait
blocks the main queue in your example. You can dispatch the async task to a different queue:Or use some other system, like NSRunLoop:
I think the better solution will be NSRunLoop as given below. It's simple and working fine.
Using an NSRunLoop is the easiest to do here.
You can try to use NSOperations for this doing your things asynchronously.