I want to wrap an async API that look like this:
[someObject completeTaskWithCompletionHandler:^(NSString *result) {
}];
into a synchronous m
dispatch_semaphore_wait
blocks the main queue in your example. You can dispatch the async task to a different queue:
__block NSString *returnResult;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
dispatch_async(queue,^{
result = [someObject completeTaskSynchronously];
});
Or use some other system, like NSRunLoop:
__block finished = NO;
[self completeTaskWithCompletionHandler:^(NSString *result) {
resultResult = result;
finished = YES;
}];
while (!finished) {
// wait 1 second for the task to finish (you are wasting time waiting here)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
I think the better solution will be NSRunLoop as given below. It's simple and working fine.
- (NSString *)getValue {
__block BOOL _completed = NO;
__block NSString *mValue = nil;
[self doSomethingWithCompletionHandler:^(id __nullable value, NSError * __nullable error) {
mValue = value;
_completed = YES;
}];
while (!_completed) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
return mValue;
}
You can try to use NSOperations for this doing your things asynchronously.
Using an NSRunLoop is the easiest to do here.
__block NSString* result = nil;
[self completeTaskWithCompletionHandler:^(NSString *resultstring) {
result = resultstring;
}];
while (!result) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}