You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Swift项目中WKWebView的evaluateJavaScript执行完成后再执行后续代码

解决WKWebView中evaluateJavaScript异步执行的问题

这个问题我太熟悉了!WKWebView的evaluateJavaScript是异步执行的——它不会阻塞当前线程等待JS代码跑完,而是直接继续执行后面的代码,这就是为啥你的print(items)总是先输出,而此时items还没被填充。

下面给你两种最常用的解决方案,适配不同的Swift版本:

方案1:利用Completion Handler闭包(兼容所有Swift版本)

把需要在JS执行完成后才做的操作(比如填充items、打印结果)全部放到evaluateJavaScript的完成闭包里,这样就能保证代码执行顺序。

举个具体的例子:

var items: [String] = []

// 第一步:先获取页面中item的数量
webView.evaluateJavaScript("document.querySelectorAll('.target-item').length") { result, error in
    // 先处理错误
    if let jsError = error {
        print("JS执行出错:\(jsError.localizedDescription)")
        return
    }
    
    guard let itemCount = result as? Int else {
        print("无法解析JS返回的结果")
        return
    }
    
    // 第二步:遍历获取每个item的内容
    for index in 0..<itemCount {
        self.webView.evaluateJavaScript("document.querySelectorAll('.target-item')[index].textContent") { itemResult, itemError in
            if let itemText = itemResult as? String {
                self.items.append(itemText)
                
                // 当最后一个item处理完时,再打印结果
                if index == itemCount - 1 {
                    print("最终填充的items:\(self.items)")
                }
            }
        }
    }
}

// ❌ 不要在这里print(items)!这里的代码会先于上面的闭包执行

方案2:使用Async/Await(Swift 5.5+ 推荐)

从Swift 5.5开始,苹果为WKWebView提供了异步版本的evaluateJavaScriptAPI,用async/await语法可以彻底告别嵌套闭包的“回调地狱”,代码可读性更强:

var items: [String] = []

// 要在异步上下文(比如Task、async函数)中调用
Task {
    do {
        // 等待JS执行完成,获取item数量
        let itemCount = try await webView.evaluateJavaScript("document.querySelectorAll('.target-item').length") as! Int
        
        // 遍历获取每个item的内容
        for index in 0..<itemCount {
            let itemText = try await webView.evaluateJavaScript("document.querySelectorAll('.target-item')[index].textContent") as! String
            items.append(itemText)
        }
        
        // 现在所有JS操作都完成了,安全打印items
        print("最终填充的items:\(items)")
    } catch {
        print("执行过程出错:\(error.localizedDescription)")
    }
}

核心原理总结

evaluateJavaScript的设计就是异步的——它把JS代码的执行交给WebKit的后台线程处理,当前线程(通常是主线程)会继续执行后续代码。所以你必须把依赖JS执行结果的逻辑,放到它的完成回调里,或者用async/await等待异步任务完成,才能保证代码的执行顺序符合预期。

内容的提问来源于stack exchange,提问作者Jef Roosens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:55:38