WKScriptMessageHandlerWithReply 委托方法在非主线程上调用

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

我正在使用

WKScriptMessageHandlerWithReply
接收来自
WKWebView
的消息。

我最近重构了代码,将视图相关代码和逻辑相关代码分离成

WebViewController
/
WebController

class WebController: NSObject {
    func performSomeAction() async -> (Any?, String?) {
        // ...
    }
}

extension WebController: WKScriptMessageHandlerWithReply {
    func userContentController(_: WKUserContentController, didReceive message: WKScriptMessage) async -> (Any?, String?) {
        guard message.name == MESSAGE_HANDLER_NAME else {
            return
        }

        if message.body == "some_event_name" {
            return async performSomeAction()
        }

        return (nil, "unknown event")
    }
}

自从这次重构以来,该方法仍然可以正常调用,但不再在主线程上。但是

WKScriptMessage
的属性只能在主线程中访问:

Main Thread Checker: UI API called on a background thread: -[WKScriptMessage name]

为什么这种行为会改变?解决这个问题的好方法是什么?

swift async-await wkwebview wkscriptmessage
1个回答
0
投票

当接收者是

WKScriptMessageHandlerWithReply
的子类时,默认在主线程调用
UIResponder
的委托方法,其中也包括
UIViewController

但是通过新的设置,

WebController
NSObject
的子类,这会导致在随机线程上调用委托方法。

为了确保委托方法在主线程上被调用,您可以使用

@MainActor
注释该方法。

extension WebController: WKScriptMessageHandlerWithReply {
    @MainActor
    func userContentController(_: WKUserContentController, didReceive message: WKScriptMessage) async -> (Any?, String?) {
        guard message.name == MESSAGE_HANDLER_NAME else {
            return
        }

        if message.body == "some_event_name" {
            return async performSomeAction()
        }

        return (nil, "unknown event")
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.