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

问题描述 投票:0回答:2

WKWebView
尝试在 Xcode 14.1 上使用 Swift 评估 JavaScript 时崩溃,在 iOS 上进行了测试,但在 macOS 上应该有相同的行为。

我做了一个非常简化的示例来尝试找到解决方案,但它不断崩溃:

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

:0:致命错误:隐式解包时意外发现 nil 可选值

ios swift wkwebview fatal-error evaluatejavascript
2个回答
5
投票

问题的一部分似乎是方法重载,从 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
版本时,
WKWebView
期望JavaScript返回一个值(
Void
以外的值),如果您评估的JavaScript没有返回值,您将发生车祸。

解决方案

选项1

始终确保 JavaScript 返回一个值。

崩溃:

try? await webView.evaluateJavaScript("console.log('hello world')") // fatal error

不崩溃:

try? await webView.evaluateJavaScript("console.log('hello world'); 0")

选项2

当无法显式返回值时,请使用具有完成处理程序的签名(即使您传递 nil 作为处理程序)。

webView.evaluateJavaScript("console.log('hello world')", completionHandler: nil)

0
投票

另一种选择可能是这样的:

@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()
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.