Skip to main content

Command Palette

Search for a command to run...

iOS: Observing WKWebView Sub-Routes

Published
2 min read

While using WKWebView in your app, you might head into a situation to observe every URL that is traversed by the user. For Example, you are loading the URL “https://hashnode.com/” into the webview.

override func viewDidLoad() {
   super.viewDidLoad()
   guard let hashnodeURL = URL(string: "https://hashnode.com/") else {    return }
   let urlRequest = URLRequest(url: hashnodeURL)
   webView.load(urlRequest)
}

You can conform to the WKNavigationDelegate protocol by webView.navigationDelegate = self in order to observe every URL that is traversed by the user and you could write your business logic in the below method

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void){
//… Your business logics go here…
}

All seems to be working right, isn’t it? The real problem occurs when you want to perceive the sub-routes(“/community”,”/explore”). For Example, if you want to perceive whether the user had traversed to https://hashnode.com/community by clicking on the webview. You might notice that the above method decidePolicyFor navigationAction, might not be called for any other sub-routes unless you are redirected to another URL host (or) webView.load(request: URLRequest) is called manually.

So, in order to perceive the user traversed URL within the same host. We need to use KVO(Key-Value Observing) in swift. You could achieve this by adding an observer for keypath URL in WKWebView properties before loading the request in the webView.

override func viewDidLoad() {
   super.viewDidLoad()

   guard let hashnodeURL = URL(string: "https://hashnode.com/") else {    return }

   let urlRequest = URLRequest(url: hashnodeURL)

   // Add Observer before loading your URLRequest in order to perceive each URL change.
   webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)

   webView.load(urlRequest)
}

Next, you need to observe the changes by overriding the method “observeValue” in the ViewController.

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  //… Your business logics go here…
  // You can also compare your host (or) keypath and write your business logics over here..
  guard webView.url?.host == "Your Specified Domain Host" else { return }
}

That’s everything. I hope you enjoyed reading it. Happy Coding!!!

More from this blog

Rasik Blog

9 posts