The following code should send a message from the watch to the iPhone. Unfortunately, it is crashing. I have no clue why.
if WCSession.isSupported()
{
let session = WCSession.default
if ((session.activationState == .activated) && session.isReachable)
{
session.sendMessage(["SimpleMessages":["start"]], replyHandler:{reply in
_ = 0
},
errorHandler:nil)
}
}
If the reply handler is set to nil, the code does not crash.
Anyway, in both cases the message is correctly sent from the watch to the phone.
The code itself is run on the main thread (verified).
I am running watchOS 26.6 and iOS 27.
Here is the crash :
This is one of a class of problems related to the way that Swift concurrency treats methods with callback from Objective-C. Swift is expecting the callback to be delivered on the main actor. That’s not the defined semantics of the sendMessage(_:replyHandler:errorHandler:) method, and hence you end up trapping inside the Swift runtime.
My general advice on this front is to switch to the Swift async function variant of the method. However, that won’t work in this case; Swift doesn’t create an async function variant of this method because it’s not sure which callback is the correct completion handler.
Given that, your best option is to mark the callback closures as sendable:
session.sendMessage(
…,
replyHandler: { @Sendable reply in
…
},
errorHandler: { @Sendable error in
…
}
)
This tells the compiler that the callbacks are safe to call from any context, and thus it won’t insert its main actor check.
IMPORTANT The real fix for this problem would be for Apple to annotate the Watch Connectivity framework headers so that the Swift compiler knows that these closures are not called on the main actor. As you work with Watch Connectivity you’ll find other cases where this is an issue. For example, the session delegate methods (WCSessionDelegate) are called from a background queue but Swift doesn’t know that. There are fixes for all of these issue, but it’s not a smooth path.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"