iOS: Observing WKWebView Sub-Routes
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!!!