在web中注入代码通常使用的都是addUserScript(), 例如:
let script = "window.IOSMobileApp = true;"
let userScript = WKUserScript(source: script, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let userContentController = WKUserContentController()
userContentController.addUserScript(userScript)
但是,实际使用的时候有的web界面已经成功注入了代码,却不会生效。所以需要更早的注入代码来实现,发现
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!)方法中执行 evaluateJavaScript() 会比 addUserScript() 更早的注入js代码到web中去。
通过研究发现
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!)
调用时机:
- Main Frame开始加载时
- 当Main Frame开始接收网页内容时调用
- 此时已收到服务器的初始化响应
- DOM开始构建但尚未完成 document.readyState为loading
- 页面重定向
- 每次服务器端重定向(Http 3xx)后
- 重定向链中的每个目标URL开始加载时会触发
- 前进/后退导航时
- 使用历史记录导航(前进/后退)时
- 页面加载前触发
- iframe加载时
- 如果实现了webView(_: didCommit: )且没有限制Main Frame
- 但通常只关注主框架的加载
使用场景
显示加载进度 / 重置页面状态 / 注入早期脚本
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
// 显示加载进度
progressView.isHidden = false
progressView.setProgress(0.1, animated: true)
// 重置页面状态
errorView.isHidden = true
// 清除前一个页面的临时数据
tempData = nil
// 注入早期脚本
let jsCode = "window.iOSApp = true;"
webView.evaluateJavaScript(jsCode) { result, error in
if let res = result as? Bool {
print("执行结果\(res)")
} else if let error = error {
print("失败\(error.localizedDescription)")
} else {
print("js无效")
}
}
}
其他方法的执行顺序
- webView(_:decidePolicyFor: decisionHandler: ) -> 用户同意导航后
- webView(_:didStartProvisionalNavigation: ) -> 导航开始
- webView(_:didCommit: ) -> 内容开始加载
- webView(_:didFinish: ) -> 内容加载完成