-1

I have a WebView app which contains external links that I wish to have users open within Safari as opposed to the webview itself, on tap. I believe it has something to do with a Navigation Delegate but I am new to iOS Dev and have no idea where to start! Below is my code as it is today. If you can tell me specifically what changes to make and where to put in any code, that would make my life so much easier. Thanks everyone in advance for any help! I think there's a way along the lines of setting a Navigation delegate such that all URL's that start with https://example-root.com/ open normal, in the webview since they are native nav buttons but all other URL's I want to open in safari on tap.

import UIKit
import WebKit


class ViewController: UIViewController {


let webView: WKWebView = {
 let prefs = WKWebpagePreferences()
 prefs.allowsContentJavaScript = true
 let configuration = WKWebViewConfiguration()
 configuration.defaultWebpagePreferences = prefs
 let webView = WKWebView(frame: .zero, configuration: configuration)
 
 return webView
 }()

override func viewDidLoad() {
 super.viewDidLoad()
 view.addSubview(webView)
 // Do any additional setup after loading the view.
 
 guard let url = URL(string: "https://example-root.com/") else {
   return
 }
 webView.load(URLRequest(url: url))
 
 
 
 DispatchQueue.main.asyncAfter(deadline: .now()+5) {
   self.webView.evaluateJavaScript("document.body.innerHTML") { result, error in guard lethtml = result as? String, error == nil else {
       return
     }
   }
   
  }
  }
  override func viewDidLayoutSubviews() {
 super.viewDidLayoutSubviews()
 webView.frame = view.bounds
  }

}

1 Answers1

0

You're right that you'll need to use the NavigationDelegate to intercept the navigation action. Make your ViewController conform to WKNavigationDelegate and implement the webView(_:decidePolicyFor:decisionHandler:) method:

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

        if let url = navigationAction.request.url, !url.host.contains("example-root.com") {
            UIApplication.shared.open(url)
            decisionHandler(.cancel)
            return
        }
        decisionHandler(.allow)
    }
}

Don't forget to set the navigationDelegate property of your WKWebView, you can do this in viewDidLoad with the following:

webView.navigationDelegate = self
samaitch
  • 1,172
  • 7
  • 9
  • I don't have the reputation yet to upvote your solution but thank you for the answer!! – Joseph Pino Jun 22 '21 at 19:45
  • Sorry, should be `navigationDelegate`, have updated the answer. – samaitch Jun 23 '21 at 16:42
  • The extension shouldn't be nested inside any other declaration, so put it either **before** your `class ViewController: UIViewController` declaration, or, more usually, put it at the bottom of your file **after** the final closing `}` of your `ViewController` class. – samaitch Jun 23 '21 at 17:32
  • You could use `!url.absoluteString.starts(with: "https://example-root.com/")` but this wouldn't catch any subdomains, maybe use `!url.host.contains("example-root.com")` instead of the equality check, have updated the answer. – samaitch Jun 23 '21 at 17:55
  • Works with the !url.absolute one and since my root domain is webflow the url breadcrumbs dont pose a problem with subdomains. THANK YOU SO MUCH! – Joseph Pino Jun 23 '21 at 18:23
  • @JosephPino you have the reputation to _accept_ this answer. – matt Jun 23 '21 at 19:49