在使用WKWebView时,如何捕获重定向URL,例如当网页在提交用户名和密码或其他数据时重定向到另一个页面。我需要捕获重定向的URL。在WKNavigationDelegate中是否有任何方法可以覆盖?
在使用WKWebView时,如何捕获重定向URL,例如当网页在提交用户名和密码或其他数据时重定向到另一个页面。我需要捕获重定向的URL。在WKNavigationDelegate中是否有任何方法可以覆盖?
(这个回答是关于如何在WKWebView中检测URL重定向的更一般问题,这是导致我访问此页面的搜索结果。)
简短回答
使用WKNavigationDelegate
的webView(_:didReceiveServerRedirectForProvisionalNavigation:)
函数,并检查WKWebView
的URL
属性。
更长的回答
你可以在几个地方检测服务器端重定向。
在iOS 10.3.3和iOS 11.0上,当加载一个被服务器重定向的URL时,我观察到的事件序列为:
对于原始URL请求,调用WKNavigationDelegate
函数webView(_:decidePolicyFor:decisionHandler:)
。WKWebView
的URL
属性设置为原始URL。
对于原始URL请求,调用WKNavigationDelegate
函数webView(_:didStartProvisionalNavigation:)
。WKWebView
的URL
属性设置为原始URL。
WKWebView
的URL
属性由WebKit更新为重定向URL。(只有在键值观察该属性时才会知道这一点。)
对于重定向URL请求,调用WKNavigationDelegate
函数webView(_:decidePolicyFor:decisionHandler:)
。WKWebView
的URL
属性然后是重定向URL。
调用WKNavigationDelegate
函数webView(_:didReceiveServerRedirectForProvisionalNavigation:)
。WKWebView
的URL
属性是重定向URL。
webView(_: decidePolicyFor: decisionHandler:)
中的URL
属性没有改变,实际上这似乎是个明智的排序方式,但我在设备上没有观察到这种情况。)webView(_:didReceiveServerRedirectForProvisionalNavigation:)
是专门用于检测重定向的目的,因此可能是首选项,尽管在步骤3或4可能也可以推断出重定向,但前提是您可以确信没有其他导航更改的原因。didReceiveServerRedirectForProvisionalNavigation
应该是正确的方法。 - Rexam使用此 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)
}
希望这可以帮助到你
在尝试了所有解决方案之后,这个使用Swift 5和WKWebView的解决方案最终对我有用。此解决方案为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()
}
Swift 5 火爆
非常简单的方法
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
if let url = webView.url?.absoluteString{
print("url = \(url)")
}
}
对我来说,使用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
}
}
deinit
或viewWillDisappear
上移除观察者。 - Daniel Hu感谢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
}
}
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
let urlString = navigationAction.sourceFrame.request.url?.absoluteString ?? ""
print("\(urlString)")
decisionHandler(.allow)
}