WKWebView not opening custom URL scheme (js opens custom scheme link in new window)

Ok, figured this out... happens that the link was opening in new window, so adding next code along with setting UIDelegate made it work

    // Somewhere in viewDidLoad()...
    myWebView.UIDelegate = self;
}

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    NSLog(@"createWebViewWithConfiguration %@ %@", navigationAction, windowFeatures);
    if (!navigationAction.targetFrame.isMainFrame) {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
        [(WKWebView *)_webView loadRequest:navigationAction.request];
    }
    return nil;
}

-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{

    NSURLRequest *request = navigationAction.request;
    if(![request.URL.absoluteString hasPrefix:@"http://"] && ![request.URL.absoluteString hasPrefix:@"https://"]) {
        if([[UIApplication sharedApplication] canOpenURL:request.URL]) {
            //urlscheme, tel, mailto, etc.
            [[UIApplication sharedApplication] openURL:request.URL];
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

Note: This answer is just focus on urlscheme, but maybe lead to other problems. Thanks for your feedback!


The following works in Swift 5.1 on iOS 13.1.3 (variation of @hstdt's answer) for WKWebView handling minimally the following (tested) schemas: sms:, tel:, and mailto:.

Add the following to whereever you're setting up your WKWebView.

// assign the delegate
webView.navigationDelegate = self

Then, add the following function somewhere in your class.

func webView(_ webView: WKWebView,
             decidePolicyFor navigationAction: WKNavigationAction,
             decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    // if the request is a non-http(s) schema, then have the UIApplication handle
    // opening the request
    if let url = navigationAction.request.url,
        !url.absoluteString.hasPrefix("http://"),
        !url.absoluteString.hasPrefix("https://"),
        UIApplication.shared.canOpenURL(url) {

        // have UIApplication handle the url (sms:, tel:, mailto:, ...)
        UIApplication.shared.open(url, options: [:], completionHandler: nil)

        // cancel the request (handled by UIApplication)
        decisionHandler(.cancel)
    }
    else {
        // allow the request
        decisionHandler(.allow)
    }
}

Explanation:

  • WKWebView seems to be unequipped to handle non-http(s) url schemas.
  • The above code catches the request before WKWebView has a chance to render/load it to check for a different schema.
  • We check for a non-http(s) schema and have the UIApplication handle it instead.

Note: Comment if you find other schemas working or not working using this solution.

Again, this solution was sourced and modified from @hstdt's answer.