Open3

Apple Watch: sendMessage/didReceiveMessageで混乱する

kabeyakabeya

WatchConnectivityの送信側のsendMessage(_:replyHandler:errorHandler:)と、受信側のsession(_:didReceiveMessage:replyHandler:)の利用部分の処理を改めて見直していて、混乱しました。

Apple Watch→iPhoneに送信するとして、送信側で指定したreplyHandlerクロージャが、アーキテクチャも違うのにどうやって受信側のreplyHandlerとして渡ってくるの?という疑問です。

何のことはない、同じ名前ですが違うものでした。
sendMessagemessageと、didReceiveMessagemessageは同じですが、replyHandlerは全く違います。

送信側のreplyHandlerにnilではなく(応答データ処理用)クロージャ(a)を渡すと、受信側のreplyHandlerに(WatchConnectivity標準の)返信用データ送信用クロージャ(b)が渡ってきます。
(a)は自分で書きますが、(b)は自分で書いたものではありません。

受信側では必ずreplyHandlerを呼べ、ということだったので何の気なしに呼んでいましたが、よくよく見直したときにそもそも何なんだこれは?となってちょっと混乱した、という話でした。

ちなみに、送信側でreplyHandlerにnilを渡すと、受信側はsession(_:didReceiveMessage:replyHandler:)ではなくreplyHandlerのないsession(_:didReceiveMessage:)のほうが呼ばれます。
(ということになっていますが、replyHandlerをnilにすると動かないという情報もあります。検証はしてません)

kabeyakabeya

ちなみに、送信側でreplyHandlerにnilを渡すと、受信側はsession(_:didReceiveMessage:replyHandler:)ではなくreplyHandlerのないsession(_:didReceiveMessage:)のほうが呼ばれます。
(ということになっていますが、replyHandlerをnilにすると動かないという情報もあります。検証はしてません)

この、replyHandler:のないほうをSwift Concurrencyでasyncに書き換えようとしましたが、これダメですね。

sendMessageerrorHandler:はエラーがあれば非同期で後から呼ばれてしまうので、エラーがないときにどうなるのかというと、たぶんreplyHandler:がないと正常に終わったか分からない。

replyHandler:のない版は、もう放り投げて終わり、届いたかどうかも気にせず、エラーがあってもどうでもいい(少なくともそこでリカバリとかはしない)、というぐらいのケースにしか使えないように思えます。

kabeyakabeya

sendMessageのerrorHandler:はエラーがあれば非同期で後から呼ばれてしまうので、エラーがないときにどうなるのかというと、たぶんreplyHandler:がないと正常に終わったか分からない。

Swift Concurrencyだと、正常時にcontinuation.resume()を呼んでやる必要がありますが、それを呼ぶタイミングがありません。