在 ios 中的 wkwebview 中捕获重定向 url

Capture redirect url in wkwebview in ios

如何在使用 WKWebView 时捕获重定向 url ,例如网页在提交用户名和密码或其他一些数据时重定向到另一个页面。我需要捕获重定向的 url。 WKNavigationDelegate中有没有方法可以覆盖?

使用这个WKNavigationDelegate方法

public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
        if(navigationAction.navigationType == .other) {
            if let redirectedUrl = navigationAction.request.url {
                //do what you need with url
                //self.delegate?.openURL(url: redirectedUrl)
            }
            decisionHandler(.cancel)
            return
        }
        decisionHandler(.allow)
    }

希望对您有所帮助

(这回答了如何检测 WKWebView 中的 URL 重定向这个稍微更一般的问题,这是引导我到此页面的搜索。)

简答

使用 WKNavigationDelegatewebView(_:didReceiveServerRedirectForProvisionalNavigation:) 函数并检查 WKWebViewURL 属性.

更长的答案

有几个地方可以检测到服务器端重定向。

在 iOS 10.3.3 和 iOS 11.0 上,我在加载被服务器重定向的 URL 时观察到的事件顺序是:

  1. WKNavigationDelegate函数 webView(_:decidePolicyFor:decisionHandler:) 被称为 原始 URL 请求。 WKWebViewURL 属性 设置为 原文URL.

  2. 调用 WKNavigationDelegate 函数 webView(_:didStartProvisionalNavigation:) 原始 URL 请求。 WKWebViewURL 属性 设置为 原文URL.

  3. WKWebViewURL 属性 被 WebKit 更新为重定向 URL。 (如果你是键值对,你只会知道这一点 观察 属性.)

  4. 调用 WKNavigationDelegate 函数 webView(_:decidePolicyFor:decisionHandler:) 重定向 URL 请求。 WKWebViewURL就是属性 重定向 URL.

  5. WKNavigationDelegate函数webView(_:didReceiveServerRedirectForProvisionalNavigation:)是 叫。 WKWebViewURL属性是 重定向 URL.

(注意:在 iOS 11.0 模拟器上,我看到步骤 3 和 4 颠倒了, URL 属性 在 webView(_:decidePolicyFor:decisionHandler:) 中没有变化,这实际上看起来像合理的顺序,但我没有在设备上观察到这一点。)

似乎 webView(_:didReceiveServerRedirectForProvisionalNavigation:) 是为检测重定向而明确构建的,因此可能是首选选项,尽管重定向可能会在步骤 3 或 4 中推断出来,但前提是您可以确定没有其他导航变化的原因。

感谢 Sven: https://forums.developer.apple.com/thread/117073

如果您遇到 WebView 无法打开 PDF 文件或只是 url 解析为空的情况,因为 WebView 的重定向 URL 没有通过,您可以使用WKUIDelegate 函数 webView(_:createWebViewWith:for:windowFeatures:) 捕获失败的调用并再次加载请求,如:

extension WebViewWrapper: WKUIDelegate {

 func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
     if navigationAction.targetFrame == nil || navigationAction.targetFrame?.isMainFrame == false {
         webView.load(navigationAction.request)
     }
     return nil
 }

}

对我来说,使用 decidePolicyFor 导航委托的方法没有用

因为 WKNavigationDelegate 的方法

它没有工作
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)

只有在整页重新加载时才会调用。 为了能够捕获所有 WKWebView 的请求 URL 更改,必须在 WKWebView 的 URL 属性.

上放置一个键值观察器

首先,在viewDidLoad中添加:

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

其次,添加observeValue方法

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == #keyPath(WKWebView.url) {
            // Whenever URL changes, it can be accessed via WKWebView instance
            let url = webView.url
        }
    }

在尝试了所有的解决方案之后,最后这个解决方案对我有用 Swift 5 和 WKWebView.This 解决方案为 Swift

实现了 KVO
var webView: WKWebView?
var webViewObserver: NSKeyValueObservation?

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    webView = WKWebView(frame: self.view.bounds)
    webViewObserver = webView?.observe(\.url, options: .new, changeHandler: {
        (currentWebView, _) in
        //      Here you go the new path
        currentWebView.url
    })
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    webViewObserver?.invalidate()
}

使用这个 WKNavigationDelegate 方法。我从 sourceFrame.request

得到重定向 url
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
        let urlString = navigationAction.sourceFrame.request.url?.absoluteString ?? ""
        print("\(urlString)")
        decisionHandler(.allow)
 }

Swift 5 繁荣

非常简单的方法

func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
    if let url = webView.url?.absoluteString{
        print("url = \(url)")
    }
}