Lance Samaria
Lance Samaria

Reputation: 19622

How to open external link with WKWebView once already inside WebView?

I've been on youtube, SO, and google for the last 3 hrs, I can't find the answer.

I can open the initial link to instagram via webView, once I'm inside the webView and I go to someone's bio and press whatever link they have nothing happens.

I went to my .plist and enabled App Transport Security > Arbitrary Loads > YES

enter image description here

I tried decidePolicyFor navigationAction: WKNavigationAction but nothing happens:

class ViewController: WKNavigationDelegate {

    var webView: WKWebView!

    override func loadView() {
        webView = WKWebView()
        webView.navigationDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let url = URL(string: "https://www.instagram.com/apple") else { return }
        let request = URLRequest(url: url)

        webView.load(request)
        webView.allowsBackForwardNavigationGestures = true

        webView.addObserver(self, forKeyPath: #keyPath(WKWebView.isLoading), options: [.new], context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "loading" {
            if webView.isLoading {
                view.addSubview(spinner)
            } else {
                spinner.removeFromSuperview()
            }
        }
    }

    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        if navigationAction.targetFrame == nil {
            webView.load(navigationAction.request)
        }
        return nil
    }

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

        switch navigationAction.navigationType {
        case .linkActivated:
            if navigationAction.targetFrame == nil {
                self.webView?.load(navigationAction.request)
            }
            if let url = navigationAction.request.url, !url.absoluteString.hasPrefix("http://www.myWebSite.com/example") {
                DispatchQueue.main.async {
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                }
                print(url.absoluteString)
                decisionHandler(.cancel)
                return
            }
        default:
            break
        }

        if let url = navigationAction.request.url {
            print(url.absoluteString)
        }
        decisionHandler(.allow)
    }

    // tried this too
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        var action: WKNavigationActionPolicy?

        defer {
            decisionHandler(action ?? .allow)
        }

        guard let url = navigationAction.request.url else { return }

        print(url)

        if navigationAction.navigationType == .linkActivated, url.absoluteString.hasPrefix("http://www.example.com/open-in-safari") {
            action = .cancel
            DispatchQueue.main.async {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
        }
    }
}

Upvotes: 1

Views: 6303

Answers (1)

Isuru
Isuru

Reputation: 31323

You need to conform to the WKUIDelegate as well.

webView.uiDelegate = self

Because you haven't, this delegate method isn't firing.

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView?

Upvotes: 2

Related Questions