I am deprecating iOS 9 on a project. One of the differences in the framework is that the openURL method has changed.

iOS 9

- (BOOL)openURL:(NSURL *)url;

iOS 10

- (void)openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options completionHandler:(void (^)(BOOL success))completion;

Notice how the method changed from being synchronous to asynchronous.

Since I have a bunch of usages for the synchronous method, I want to create a synchronous wrapper around the asynchronous openURL:options:completion: method and I'm going to update the usages to call this asynchronous wrapper instead.

My first attempt looks like this:

- (BOOL)sync_openURL: (nullable NSURL *)url {
    __block BOOL result = nil;
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [self openURL:url options:@{} completionHandler:^(BOOL success) {
        result = success;
    while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]];
    return result;

Is this a good replacement ? Can it be improved in anyway ?

  • 1
    \$\begingroup\$ Why don't you want to make your code asynchronous? \$\endgroup\$ Feb 20 '18 at 13:08

That code should work, but blocking the main thread is never a good idea. That's why the method was changed in the first place.

I suggest a deeper refactor of your code so that you use the new async method with completion handler as intended.


You don't need to do anything special here. Just change to the new method and ignore the completion handler.

[application openURL:url options:@{} completionHandler:nil];

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.