页面加载后调用 WKWebViewdecidePolicyFor

nfa*_*chi 4 ios swift wkwebview

我尝试在 WKWebView 加载之前捕获要加载的 url。根据文档decidePolicyFor navigationAction(WKNavigationDelegate)应该可以完成这项工作,但我的问题是这个委托在新网址加载之后而不是之前被调用。

这是我写的扩展。

extension MyWebViewController: WKNavigationDelegate {

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

        guard let navigationURL = navigationAction.request.url else {
            decisionHandler(.allow)
            return
        }

        let forbiddenUrlPattern = Configuration.current.links.forbiddenUrlPattern
        if forbiddenUrlPattern.matches(url: navigationURL) {
            decisionHandler(.cancel)
            showFullScreenError(error: .forbidden)
            return
        }

        // Default policy is to allow navigation to any links the subclass doesn't know about
        decisionHandler(.allow)
    }
}
Run Code Online (Sandbox Code Playgroud)

*PS 匹配扩展会检查模式并且工作正常。现在的问题是,在调用此委托函数之前,forbiddenUrl 的内容显示了一段时间,然后错误页面出现在屏幕上,如果我关闭它,最后一个可见的网页来自禁止链接模式。

在实际将链接加载到 webView 中之前,有什么方法可以了解该链接吗?

我正在使用 Xcode 11.2.1 和 Swift 5.0

nfa*_*chi 5

我写下了在这里找到的答案,它也可能对其他人有帮助。经过一番努力,我发现decisionHandler如果 url 是相对的(不是绝对 url),就不会被调用。那么为什么decisionHandler加载该页面后会被调用呢?我发现的答案是:当我们有像href:"/foo/ba"then 这样的 url 时,在调用该 url 后,它将加载并解析为www.domain.com/foo/ba,然后desicionHandler才被调用。当我想在 webView 中第一次加载 url 时
也只调用一次。didCommit

所以解决方案对我有帮助是向 webView 添加观察者

webView.addObserver(self, forKeyPath: "URL", options: [.new,.old], context: nil)
Run Code Online (Sandbox Code Playgroud)

override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        /// This observer is in addition to the navigationAction delegate to block relative urls and intrrupt them and do native
        /// action if possible.
        if let newValue = change?[.newKey] as? URL, let oldValue = change?[.oldKey] as? URL, newValue != oldValue {
            let forbiddenUrlPattern = Configuration.current.links.forbiddenUrlPattern
        if forbiddenUrlPattern.matches(url: newValue) {
            showFullScreenError(error: .forbidden)
            return
        }

                /// These two action needed to cancel the webView loading the offerDetail page.
                /// otherwise as we stop loading the about to start process webView will show blank page.
                webView.stopLoading()
                ///This is small extension for make webView go one step back
                webView.handleBackAction(sender: newValue)
                return
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

因此,这个观察者除了decisionHandler可以覆盖任何人想要监听并在需要时采取行动的绝对和相对 URL。