WKWebView执行evaluateJavaScript返回JavaScript对象格式错误如何解决
问题根因
你遇到的语法错误本质是两个问题导致的:
- 你在Swift中打印的带
=、分号格式的对象,是Swift/Objective-C对字典类型的默认调试输出格式,不是合法的JavaScript对象语法。你直接把Swift侧拿到的解析后对象用\(object)插值到JS执行字符串时,等于把这种不符合JS语法的内容直接插入到了JS代码中,自然会触发Unexpected token '='的语法错误。 - 额外的时序隐患:
evaluateJavaScript是异步执行方法,你先后两次调用分别定义parse函数、执行parse(),很可能出现parse函数还没完成定义,后面的调用就已经执行的问题。
解决方案
你完全不需要把JSON解析后拿回Swift侧再传递给JS,直接利用已经序列化好的JSON字符串即可,因为标准JSON格式本身就是合法的JS对象字面量,可以直接在JS代码中使用。
修正后的代码
let statDict: [String: Any] = [ "income" : account.stat.income, "expense" : account.stat.expense, "summary" : account.stat.summary, "incomeShorten" : account.stat.incomeShorten, "expenseShorten" : account.stat.expenseShorten, "summaryShorten": account.stat.summaryShorten ] let accountDict: [String: Any] = [ "id": account.id, "name": account.name, "description": "", "icon": account.icon, "currency": account.currency, "customer_contact_id": account.customer_contact_id ?? 0, // 转成Bool类型,JSON序列化后会输出true/false而非0/1,符合你的预期格式 "is_archived": Bool(truncating: account.is_archived as NSNumber), "sort": account.sort, "create_datetime": account.create_datetime, "update_datetime": account.update_datetime ?? "", "stat": statDict ] do { let accountData = try JSONSerialization.data(withJSONObject: accountDict) guard var accountString = String(data: accountData, encoding: .utf8) else { return } // 转义JSON中的单引号,避免打断JS字符串 accountString = accountString.replacingOccurrences(of: "'", with: "\\'") // 合并所有JS逻辑为一段,一次执行避免异步嵌套问题 let jsCode = """ const account = JSON.parse('\(accountString)'); window.emitter.emit('openDialog', 'Account', account); window.emitter.on('closeDialog', function() { window.webkit.messageHandlers.emitterMessage.postMessage('closeDialog'); }); window.emitter.on('createAccount', function() { window.webkit.messageHandlers.emitterMessage.postMessage('createAccount'); }); """ webView.evaluateJavaScript(jsCode) { _, error in if let error = error { print("JS执行错误: \(error)") } } } catch { print("JSON序列化失败: \(error)") }
额外优化建议
- 不要使用
try!处理JSON序列化,一旦序列化失败会直接导致App崩溃,改用do-catch捕获异常更安全。 - 所有JS逻辑可以合并为一段一次执行,不需要多次调用
evaluateJavaScript,既减少异步回调嵌套,也能避免不同JS执行片段的时序问题。 - 如果需要输出布尔值类型的字段,在构造Swift字典时就把对应值转为
Bool类型,JSONSerialization会自动将其序列化为JSON标准的true/false格式。
内容的提问来源于stack exchange,提问作者andrey leganov
相关产品推荐
相关产品推荐

