WKWebView连续回退超2步时evaluateJavaScript执行异常问题
WKWebView连续回退后evaluateJavaScript执行页面错误的解决方案
我之前也碰到过一模一样的问题!核心原因其实是WKWebView的回退操作是异步的,你调用goBack()之后,页面并不会立刻完成跳转加载,这时候如果马上执行evaluateJavaScript(),JS代码大概率会跑在当前还没切换走的页面上,连续回退的时候这个异步的时间差问题就会被放大,导致你看到的重复输出。
针对这个问题,我给你两个关键的解决思路,附带上具体的实现代码:
1. 依赖导航完成回调,确保JS在页面加载后执行
不要在调用goBack()之后立刻执行JS,而是等WKNavigationDelegate的didFinishNavigation回调触发后,再执行你需要的JS代码。这能保证JS是在目标回退页面上运行的。
2. 用任务队列管理连续回退请求
如果用户可能连续点击回退按钮,我们需要把回退+JS执行的任务排成队列,确保前一个回退操作完全完成(页面加载完毕)后,再处理下一个任务,避免并发操作导致的混乱。
具体实现代码(Swift为例)
首先,在你的WKWebView控制器里定义几个变量来管理队列和导航状态:
import WebKit class WebViewController: UIViewController, WKNavigationDelegate { private var webView: WKWebView! // 存储回退时需要执行的JS任务队列 private var backTaskQueue: [(() -> Void)] = [] // 标记当前是否正在处理回退导航 private var isProcessingBack = false override func viewDidLoad() { super.viewDidLoad() // 初始化WKWebView并设置delegate let config = WKWebViewConfiguration() webView = WKWebView(frame: view.bounds, configuration: config) webView.navigationDelegate = self view.addSubview(webView) // 加载初始页面(示例) let url = URL(string: "your-main-page-url")! webView.load(URLRequest(url: url)) } // 回退按钮点击事件 @objc func backButtonClicked() { guard webView.canGoBack else { return } // 将需要执行的JS操作加入队列 backTaskQueue.append { [weak self] in self?.webView.evaluateJavaScript("document.title") { result, error in if let title = result as? String { print("当前页面标题:\(title)") } if let error = error { print("JS执行错误:\(error.localizedDescription)") } } } // 如果当前没有在处理回退,就启动队列处理 if !isProcessingBack { processNextBackTask() } } // 处理队列中的下一个回退任务 private func processNextBackTask() { guard !backTaskQueue.isEmpty, !isProcessingBack else { return } isProcessingBack = true webView.goBack() } // 导航完成回调 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 如果是回退导航完成 if isProcessingBack { isProcessingBack = false // 执行队列中的第一个JS任务 let currentTask = backTaskQueue.removeFirst() currentTask() // 继续处理下一个回退任务 processNextBackTask() } } }
代码说明
backTaskQueue用来存储每次回退需要执行的JS操作,避免连续点击时的操作冲突。isProcessingBack标记当前是否正在处理回退导航,确保同一时间只有一个回退操作在进行。- 在
didFinishNavigation里,我们确认回退页面加载完成后,才执行对应的JS代码,然后再处理队列里的下一个回退请求。
这样修改后,你再连续点击回退按钮,evaluateJavaScript就会在正确的历史页面上执行,输出的标题顺序就会是Details -> User Info -> Main,完全符合预期了。
内容的提问来源于stack exchange,提问作者Rhetorical
相关产品推荐
相关产品推荐

