WKWebView decidePolicyFor 在页面加载后被调用
WKWebView decidePolicyFor gets called after page loaded
我尝试在加载之前捕获即将在 WKWebView 中加载的 url。根据文档 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 matches 扩展检查模式并且工作正常。
现在的问题是 forbiddenUrl 的内容在调用此委托函数之前显示了一段时间,然后错误页面出现在屏幕上,如果我关闭它,最后一个可见的网页来自 forbidden link 模式。
在将 link 实际加载到 webView 之前,有什么方法可以了解它吗?
我正在使用 Xcode 11.2.1 & Swift 5.0
我在这里写下了我找到的答案,它也可能对其他人有所帮助。
经过大量的努力,我发现如果 url 是相对的(不是绝对的 urls),则 decisionHandler
不会被调用。
那么为什么 decisionHandler
在加载该页面后被调用?
我找到的答案是:当我们有像 href:"/foo/ba"
这样的 url 时,然后在调用 url 之后,它将加载并解析为 www.domain.com/foo/ba
,然后才 desicionHandler
接到电话了。
另外 didCommit
只在我想在 webView 中第一次加载 url 时调用一次。
所以对我有帮助的解决方案是向 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
之外,这个观察者还将涵盖绝对和相对 urls 任何人都想倾听并在需要时采取行动。
我尝试在加载之前捕获即将在 WKWebView 中加载的 url。根据文档 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 matches 扩展检查模式并且工作正常。 现在的问题是 forbiddenUrl 的内容在调用此委托函数之前显示了一段时间,然后错误页面出现在屏幕上,如果我关闭它,最后一个可见的网页来自 forbidden link 模式。
在将 link 实际加载到 webView 之前,有什么方法可以了解它吗?
我正在使用 Xcode 11.2.1 & Swift 5.0
我在这里写下了我找到的答案,它也可能对其他人有所帮助。
经过大量的努力,我发现如果 url 是相对的(不是绝对的 urls),则 decisionHandler
不会被调用。
那么为什么 decisionHandler
在加载该页面后被调用?
我找到的答案是:当我们有像 href:"/foo/ba"
这样的 url 时,然后在调用 url 之后,它将加载并解析为 www.domain.com/foo/ba
,然后才 desicionHandler
接到电话了。
另外 didCommit
只在我想在 webView 中第一次加载 url 时调用一次。
所以对我有帮助的解决方案是向 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
之外,这个观察者还将涵盖绝对和相对 urls 任何人都想倾听并在需要时采取行动。