ios 在WKWebView上使用evaluateJavaScript时出现致命错误

5n0oy7gb  于 12个月前  发布在  iOS
关注(0)|答案(2)|浏览(298)

WKWebView在尝试使用Swift在Xcode 14.1上评估JavaScript时崩溃,在iOS上测试,但在macOS上也应该有相同的行为。
我做了一个大大简化的例子来试图找到解决方案,它一直崩溃:

let webView = WKWebView()
Task {
    try? await webView.evaluateJavaScript("console.log('hello world')")
}

:0:致命错误:隐式展开Optional值时意外发现nil

slsn1g29

slsn1g291#

似乎问题的一部分是方法重载,从Xcode 14.1开始,有几个名为evaluateJavaScript的方法作为WKWebView的一部分。
由于可选参数,它们似乎具有相同的签名,编译器很难理解我们指的是哪一个。

方法

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返回的值,您将崩溃。

解决方案

选项一

始终确保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)
aoyhnmkz

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()
            }
        }
    }
}

相关问题