WKWebView решитьPolicyFor вызывается после загрузки страницы - PullRequest
2 голосов
/ 29 апреля 2020

Я пытаюсь поймать URL-адрес, который нужно загрузить в WKWebView, прежде чем он загрузится. На основании документов decidePolicyFor navigationAction (WKNavigationDelegate) должен выполнить эту работу, но моя проблема заключается в том, что этот делегат вызывается после загрузки нового URL-адреса не раньше этого.

вот расширение, которое я написал.

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)
    }
}

* PS Расширение совпадений проверяет шаблон и работает нормально. Теперь проблема заключается в том, что содержимое компонентаiddenIrl некоторое время показывалось до того, как вызывается этот забавный делегат c, а затем на экран выводится страница с ошибкой, и если я закрываю ее, последняя видимая веб-страница происходит из шаблона запрещенной ссылки.

есть ли способ понять ссылку до того, как она будет загружена в webView?

Я использую Xcode 11.2.1 & Swift 5.0

1 Ответ

1 голос
/ 10 мая 2020

Я написал ответ, который нашел здесь, что он может помочь кому-то еще. После большой борьбы я узнал, что decisionHandler не будет вызван, если URL-адрес является относительным (не абсолютным URL-адресом). Так почему decisionHandler вызвали после загрузки этой страницы? я нашел ответ: когда у нас есть URL-адреса, такие как href:"/foo/ba", то после вызова этого URL-адреса он будет загружен и разрешен как www.domain.com/foo/ba, и только тогда будет вызван desicionHandler.
Также didCommit вызывается только один раз, когда я хотел впервые загрузить URL в webView.

, поэтому решение помогло мне добавить наблюдателя в webView

webView.addObserver(self, forKeyPath: "URL", options: [.new,.old], context: nil)

и

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
            }
        }
    }

Так что этот наблюдатель в дополнение к decisionHandler будет охватывать как абсолютные и относительные URL-адреса, которые каждый хочет выслушать и принять меры, если это необходимо.

...