Swift中WKWebView调用evaluateJavaScript报was invalidated错误如何解决
报错根本原因
- WKWebView生命周期错误:你将
WKWebView定义为isLoggedIn方法的局部变量,方法执行结束后局部变量会被系统回收销毁,而load页面请求、evaluateJavaScript执行JS都是异步操作,回调触发时webview已经被释放,就会抛出The WKWebView was invalidated错误。 - 同步返回逻辑错误:evaluateJavaScript的回调是异步执行的,方法末尾直接return的返回值还没等到回调修改就已经返回,永远只会返回初始值true,就算webview不报错也拿不到正确的JS执行结果。
- 实例创建逻辑错误:你调用时使用
userManager().isLoggedIn(),每次调用都会生成新的userManager临时实例,哪怕把webview设为userManager的属性,临时实例销毁时webview也会跟着释放,同样会触发报错。
修复方案
如果你需要保留WKWebView的实现逻辑,修改方式如下:
- 给userManager实现单例,避免每次调用都生成新的临时实例
- 将WKWebView升级为userManager的全局持有属性,不要定义在方法内部,避免被提前回收
- 将isLoggedIn的同步返回改为异步回调,等JS执行完成后再通过回调返回结果
修复后代码示例:
class UserManager { // 全局单例 static let shared = UserManager() // 全局持有WKWebView private var webView: WKWebView? private init() { let config = WKWebViewConfiguration() webView = WKWebView(configuration: config) } // 改为异步回调方法 public func isLoggedIn(completion: @escaping (Bool) -> Void) { guard let webView = webView, let url = URL(string: "https://www.google.com/") else { completion(false) return } webView.load(URLRequest(url: url)) // 建议监听页面load完成后再执行JS,避免页面未加载完成导致的执行错误 webView.evaluateJavaScript("document.body.backgroundColor") { result, error in if let error = error { print("JS执行错误: \(error)") completion(false) return } guard let colorStr = result as? String, colorStr.isEmpty else { completion(true) return } completion(false) } } }
调用方法示例:
// 使用单例调用,不要创建新的UserManager实例 UserManager.shared.isLoggedIn { [weak self] isLoggedIn in DispatchQueue.main.async { // 在此处处理登录状态逻辑 if isLoggedIn { // 已登录逻辑 } else { // 未登录逻辑 } } }
补充说明:如果只是需要判断登录状态,不需要引入WKWebView,直接通过HTTP请求携带Cookie请求对应校验接口实现,性能更高、逻辑更简单。
内容的提问来源于stack exchange,提问作者skillgamer
相关产品推荐
相关产品推荐

