Search code examples
hyperlinkwkwebview

Opening external links in WKWebView (not externally)


My app contains HTML information pages opened in WKWebView, containing some hyperlinks. These used to work, but stopped working with recent iOS releases with error messages, containing words

Could not create sandbox extension
Connection to daemon was invalidated

When I apply WKNavigation delegate with the following code

extension InformationPageController: WKNavigationDelegate {

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: ((WKNavigationActionPolicy) -> Void)) {
        var policy =  WKNavigationActionPolicy.allow
        if navigationAction.navigationType == .linkActivated {
            //  Neither of commented lines below works! 
            //  webView.load(navigationAction.request)
            //  webView.loadHTMLString(navigationAction.request.url!.absoluteString, baseURL: nil)
            UIApplication.shared.openURL(navigationAction.request.url!)
            policy = .cancel
        }
        decisionHandler(policy)
    }
}

the pages are opened in an external browser, but not inside the app.

Is there a way to open the links as before, within same WKWebView?


Solution

    1. It looks like only https protocol is currently accepted by WKWebView. If you have just http, WKWebView will complain about insecure protocol and won't open.

    After I changed http-s to https-s, the pages opened, but not AppStore pages. This leads to another issue.

    1. When URL address starts with https://apps.apple.com/..., iOS (but not macOS) redirects it to itms-appss://apps.apple.com/... for opening in AppStore app, causing WKWebView to come up with the error: Redirection to URL with a scheme that is not HTTP(S). Similar problem with mailto urls.

    To bypass these issues I modified code to the following:

    extension InformationPageController: WKNavigationDelegate {
        static let disallowedUrlPrefixes = ["https://apps.apple.com", "mailto:"]
    
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: ((WKNavigationActionPolicy) -> Void)) {
    
            var policy =  WKNavigationActionPolicy.allow
    
            if navigationAction.navigationType == .linkActivated,
                let url = navigationAction.request.url {
                let urlString = url.absoluteString
                if InformationPageController.disallowedUrlPrefixes.first(where:{urlString.starts(with: $0)}) != nil {
                    UIApplication.shared.openURL(url)
                    policy = .cancel
                }
            }
    
            decisionHandler(policy)
        }
    }
    

    Now the 'troublesome' pages are opened with an external browser, all others are opened within WKWebView. Unfortunately that's the best I can currently think of.