WKWeb 视图。未调用 didStartProvisionalNavigation
Posted
技术标签:
【中文标题】WKWeb 视图。未调用 didStartProvisionalNavigation【英文标题】:WKWebView. didStartProvisionalNavigation not called 【发布时间】:2016-11-21 14:25:03 【问题描述】:我在我的应用程序中使用WKWebView
,一切正常,直到用户转到money.cnn.com。对于该站点的主页,一切都很好,但是当用户离开主页并转到例如http://money.cnn.com/2016/11/21/news/dubai-trump-golf-course-developer/index.html?iid=hp-toplead-intl 或该站点上的任何其他页面时,不会调用委托方法didStartProvisionalNavigation
和didCommitNavigation
。但我需要这些方法来检测导航的开始。 decidePolicyForNavigationAction
一开始就被调用了,但是被调用了多次,我觉得使用这种方法并不是一个完美的解决方案。所以我的问题是:在这种情况下我该怎么办?在那个站点有什么特别的东西不能让WKWebView
调用它的委托方法,在这种情况下什么可能是一个可靠的解决方案?谢谢
【问题讨论】:
【参考方案1】:我不是很了解 web 开发,但在我看来,money.cnn.com 网站的 javascript 有问题。似乎站点页面之间的转换及其加载是在 JavaScript 的帮助下进行的。该 JavaScript 与本机 WKWebView 处理程序冲突。
但是!您可以在页面开头使用处理程序注入您自己的 JavaScript。当页面开始打开时,脚本将首先运行。
详情
Xcode 版本 10.2.1 (10E1001),Swift 5完整示例代码
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler
private weak var webView: WKWebView?
private lazy var scriptName = "GetUrl"
override func viewDidLoad()
super.viewDidLoad()
setupWebView()
loadUrl(string: "http://money.cnn.com/2016/11/21/news/dubai-trump-golf-course-developer/index.html?iid=hp-toplead-intl")
func setupWebView()
let contentController = WKUserContentController();
let script = "webkit.messageHandlers.\(scriptName).postMessage(document.URL)"
let userScript = WKUserScript(source: script, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true)
contentController.addUserScript(userScript)
contentController.add(self, name: scriptName)
let config = WKWebViewConfiguration()
config.userContentController = contentController
let webView = WKWebView(frame: UIScreen.main.bounds, configuration: config)
webView.navigationDelegate = self
view.addSubview(webView)
self.webView = webView
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
if message.name == scriptName
guard let url = message.body as? String else return
if url.contains("http://money.cnn.com/")
print("!!! \(url)")
else
print("??? \(url)")
func loadUrl(string: String)
guard let url = URL(string: string),
let webView = self.webView else return
webView.load(URLRequest(url: url))
Info.plist
添加 Info.plist 传输安全设置
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
或
结果
更多
Call JavaScript function from native code in WKWebView
【讨论】:
感谢您的帮助,但它不起作用。如果我按照您的示例的方式使用它,它就会起作用 - 显式加载请求。它适用于网站的主页。但是,当我从 money.cnn.com 转到 money.cnn.com/2016/11/21/news/dubai-trump-golf-course-developer/… 或任何其他子页面时,不会调用委托方法。我唯一能做的就是将 false 传递给 forMainFrameOnly 然后它也可以工作,但它会导致过于频繁地调用委托方法来加载页面上的每个资源 这很奇怪。我做了小修复并添加了控制台的屏幕截图。看一看。在我的示例中,在显示每个页面之前触发脚本。 从头开始创建了一个新项目,并在那里复制粘贴了您的代码。仅适用于第一页,即显式调用加载时。如果我进一步浏览 userContentController didReceive 消息方法永远不会被调用))) 在 func userContentController() 中,我们只检测到 money.cnn.com 页面(编辑此函数以显示所有 url)。你可能会打开另一个 cnn 网站吗? 不,方法本身没有被调用。我当然检查了【参考方案2】:将委托设置为:
webView.navigationDelegate = self
【讨论】:
以上是关于WKWeb 视图。未调用 didStartProvisionalNavigation的主要内容,如果未能解决你的问题,请参考以下文章