WKWebView在尝试使用Swift在Xcode 14.1上评估JavaScript时崩溃,在iOS上测试,但在macOS上也应该有相同的行为。我做了一个大大简化的例子来试图找到解决方案,它一直崩溃:
WKWebView
let webView = WKWebView() Task { try? await webView.evaluateJavaScript("console.log('hello world')") }
:0:致命错误:隐式展开Optional值时意外发现nil
slsn1g291#
似乎问题的一部分是方法重载,从Xcode 14.1开始,有几个名为evaluateJavaScript的方法作为WKWebView的一部分。由于可选参数,它们似乎具有相同的签名,编译器很难理解我们指的是哪一个。
evaluateJavaScript
open func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil) open func evaluateJavaScript(_ javaScriptString: String) async throws -> Any @MainActor public func evaluateJavaScript(_ javaScript: String, in frame: WKFrameInfo? = nil, in contentWorld: WKContentWorld, completionHandler: ((Result<Any, Error>) -> Void)? = nil) @MainActor public func evaluateJavaScript(_ javaScript: String, in frame: WKFrameInfo? = nil, contentWorld: WKContentWorld) async throws -> Any?
在测试了不同的场景之后,似乎当使用这些方法的async/await x版本时,WKWebView x期望JavaScript返回一个值(除了Void x之外的值),如果没有从您评估的JavaScript返回的值,您将崩溃。
async/await
Void
始终确保JavaScript返回一个值。崩溃:
try? await webView.evaluateJavaScript("console.log('hello world')") // fatal error
不崩溃:
try? await webView.evaluateJavaScript("console.log('hello world'); 0")
当不可能显式返回值时,使用带有完成处理程序的签名(即使您将nil作为处理程序)。
webView.evaluateJavaScript("console.log('hello world')", completionHandler: nil)
aoyhnmkz2#
另一种选择可能是:
@MainActor func evaluateJavaScript(string javaScriptString: String) async throws { try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in evaluateJavaScript(javaScriptString) { _, error in if let error = error { continuation.resume(throwing: error) } else { continuation.resume() } } } }
2条答案
按热度按时间slsn1g291#
似乎问题的一部分是方法重载,从Xcode 14.1开始,有几个名为
evaluateJavaScript
的方法作为WKWebView
的一部分。由于可选参数,它们似乎具有相同的签名,编译器很难理解我们指的是哪一个。
方法
在测试了不同的场景之后,似乎当使用这些方法的
async/await
x版本时,WKWebView
x期望JavaScript返回一个值(除了Void
x之外的值),如果没有从您评估的JavaScript返回的值,您将崩溃。解决方案
选项一
始终确保JavaScript返回一个值。
崩溃:
不崩溃:
选项二
当不可能显式返回值时,使用带有完成处理程序的签名(即使您将nil作为处理程序)。
aoyhnmkz2#
另一种选择可能是: