iOS WKWebView的addUserScript首次作用于about:blank页面时不生效
我之前做WKWebView相关开发的时候,正好碰到过和你一模一样的问题!给普通网站用addUserScript加脚本都好好的,唯独第一次加载about:blank页面时,脚本死活不生效,当时折腾了好一阵才摸清楚门道。
其实这是WKWebView的一个小“坑”——about:blank属于本地空白页面,它的加载流程和普通HTTP/HTTPS页面完全不一样:没有网络请求、页面资源都是本地生成的,首次加载时WebView的内部初始化状态还没完全就绪,导致你提前加到WKWebViewConfiguration里的userScript没办法被正确注入到这个空白页面中。
给你两个亲测有效的解决办法:
方法一:直接用
evaluateJavaScript注入脚本(最可靠)
放弃在WebView初始化时通过addUserScript配置脚本,等about:blank页面加载完成后,直接调用evaluateJavaScript执行你的脚本内容。这样能确保页面已经完全就绪,脚本肯定能生效。
具体代码示例:import UIKit import WebKit class ViewController: UIViewController, WKNavigationDelegate { var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() webView = WKWebView(frame: view.bounds) webView.navigationDelegate = self view.addSubview(webView) // 加载about:blank页面 webView.load(URLRequest(url: URL(string: "about:blank")!)) } // 监听页面加载完成事件,注入脚本 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { guard webView.url?.absoluteString == "about:blank" else { return } // 替换成你实际需要执行的脚本内容 let targetScript = """ document.body.style.backgroundColor = '#f0f0f0'; console.log('脚本成功注入about:blank页面啦'); """ webView.evaluateJavaScript(targetScript) { result, error in if let error = error { print("脚本执行出错:\(error.localizedDescription)") } } } }方法二:调整脚本注入时机 + 重新触发加载(备选方案)
如果你坚持要用addUserScript的方式,可以试试把脚本的注入时机改成.atDocumentEnd,然后在页面首次加载完成后重新加载一次,触发脚本注入。不过这种方法不如第一种可靠,偶尔还是会有玄学问题:import UIKit import WebKit class ViewController: UIViewController, WKNavigationDelegate { var webView: WKWebView! private var hasReloaded = false override func viewDidLoad() { super.viewDidLoad() let config = WKWebViewConfiguration() // 把注入时机改成atDocumentEnd let customScript = WKUserScript( source: "document.body.style.backgroundColor = '#f0f0f0';", injectionTime: .atDocumentEnd, forMainFrameOnly: true ) config.userContentController.addUserScript(customScript) webView = WKWebView(frame: view.bounds, configuration: config) webView.navigationDelegate = self view.addSubview(webView) webView.load(URLRequest(url: URL(string: "about:blank")!)) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 首次加载完成后重新加载,触发脚本注入 if webView.url?.absoluteString == "about:blank" && !hasReloaded { hasReloaded = true webView.reload() } } }
个人更推荐第一种方法,不仅逻辑清晰,还完全避开了WKWebView对about:blank的特殊处理逻辑,不会有奇怪的不生效问题。
备注:内容来源于stack exchange,提问作者sudoExclamationExclamation

