But since WKScriptMessageHandlerWithReply
is not
@MainActor
, neither can this method be so marked
My WebKit is kinda rusty but I believe that WKScriptMessageHandlerWithReply
should be as main-actor isolated, right? That is, all of its methods are expected to be called on the main thread?
If so, this devolves into the question “How do I tell the Swift compiler about that fact?” There are various tricks for that but I tend to reach for MainActor.assumeIsolated(_:file:line:)
:
@MainActor
class MyClass: NSObject, WKScriptMessageHandlerWithReply {
var lastMessage: WKScriptMessage? = nil
var counter: Int = 0
nonisolated func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
MainActor.assumeIsolated {
self.lastMessage = message
self.counter += 1
replyHandler(["counter": self.counter], nil)
}
}
}
This compiles without warnings in Xcode 15.3 with strict concurrency enabled. Now how it’s accessing counter
, which is main actor isolated, and using message
The docs for MainActor.assumeIsolated(…)
say:
This API should only be used as last resort, when it is not possible to express the current execution context definitely belongs to the main actor in other ways [for example] one may need to use this in a delegate style API, where a synchronous method is guaranteed to be called by the main actor
which is exactly the situation you’re in.
Note I believe that Swift 6 will have a shorthand syntax for this, but I don’t have a Swift 6 setup handy to test that right now (and I wasn’t able to quickly find the SE proposal that describes it).
Should I file a feedback for this … ?
Yes. The flip side of the doc comment above is that the framework vendor should be correctly annotating their delegate protocols. In that case that vendor is Apple, so filing a bug is appropriate.
Please post your bug number, just for the record.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"