[SWIFT] WKNavigationDelegate-decidepolicyfornavigationaction solution when called after page load

Introduction

In webView (_: decidePolicyFor: decisionHandler :), it is called when the initial page is loaded by WKWebView or when the user taps the link. I will. Therefore, by accessing WKNavigationAction, you can get the URLRequest and process whether to load the page.

So why is the title ** the solution when it is called after loading the page with WKNavigationDelegate-decidepolicyfornavigationaction **? In webView (_: decidePolicyFor: decisionHandler :), if you just load with viewdidload etc. May be called only before loading, and in subsequent WebPage transitions after loading the page

For example, if you move to a YouTube video page, it will be called after the page loads, and Apple will call it before the page loads.

Solution

The reason why it is called after loading is probably that if the URL to be loaded is a relative URL, it will not be called before loading, but after loading the page.

As an example, when you tap on the YouTube video page, it will be called before loading the video.

python


import UIKit
import WebKit

class ViewController: UIViewController {

    @IBOutlet weak var webView: WKWebView!
    
    private var _observers = [NSKeyValueObservation]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        webView.navigationDelegate = self
        webView.load(URLRequest(url: URL(string:"https://www.youtube.com/")!))
        
        _observers.append(webView.observe(\.url, options: [.new, .old]){ [weak self] _,change in
            guard let newValue = change.newValue, let oldValue = change.oldValue else { return }
            guard let newURL = newValue, let oldURL = oldValue else { return }
            
            if newURL != oldURL {
                //I want to catch with Delegate before loading Reload only when the page is called by Delegate after loading
                if newURL.absoluteString.contains("/watch"){
                    self?.webView.load(URLRequest(url: newURL))
                }
            }
        })
    }
}

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

So every time the URL of webView is changed in this way, check the URL, and if it is different from old (in the case of page transition), load again with an absolute path and webView (_: decidePolicyFor: decisionHandler :) Catch with.

Summary

Now it works as intended, but it's a violent solution. If you know a better solution, I would appreciate it if you could comment.

Thank you very much

Reference link

wkwebview-decidepolicyfor-gets-called-after-page-loaded

Recommended Posts

WKNavigationDelegate-decidepolicyfornavigationaction solution when called after page load
Solution when you are repeatedly prompted even after bundle update