【Swift/Apple Watch】iOSへデータを送受信するメソッドの違いと使い方!

この記事からわかること
- SwiftでApple Watchアプリを開発する方法
- iOSへデータを送信/受信するには?
- sendMessageメソッドの使い方
- transferUserInfo/updateApplicationContext/transferFile(_:metadata:)の違い
index
[open]
\ アプリをリリースしました /
環境
- Xcode:15.0.1
- iOS:17.0
- watchOS:10.0
- Swift:5.9
- macOS:Sonoma 14.1
iOS↔︎watchOS間でデータを送受信する方法
iOSとwatchOSの連携アプリでは両OS間でデータをやり取りすることが可能です。送受信するための方法は4種類用意されており、それぞれ挙動やできることが異なるので違いと使い方をまとめていきたいと思います。使用するメソッドはWatchConnectivity
フレームワークから提供されているおり、iOS/watchOSともに共通の実装で行うことが可能です。
データを送信するため役割を持っているのは以下の4種類です。
- sendMessage
- transferUserInfo
- updateApplicationContext
- transferFile
transferFile
メソッドを除いてですが両OS間でのデータのやり取りは辞書型[String: Any]
形式で送受信が可能になっています。
またデータの受信側はWCSessionDelegate
に準拠させることで各デリゲートメソッドよりデータを受信できるようになります。
送信できるデータ型
sendMessage
やtransferUserInfo
などのデータを送信するメソッドは[String: Any]
形式の辞書型でデータを送信できますが、サポートしているのはプロパティタイプリストのデータ型(基本的なデータ型)のみのようです。そのため独自のクラスなどはサポートされていないのでJSONなどに変換してString型として送信するのが定石です。
公式リファレンス:Property List Types and Objects
sendMessage
メソッドの定義を確認してみるとコメントの部分に「メッセージ ディクショナリはプロパティ リスト タイプのみを受け入れることができます」と記述されていました。
sendMessageメソッド
sendMessage
はペアリングされたアクティブなデバイスにメッセージを送信するメソッドです。引数replyHandler
には受け取り側にデータが到達後に実行したい処理を、引数errorHandler
では送信エラーが発生した時に実行したい処理を渡すことができます。
送信処理の実装例
受信処理の実装例
受信側はsession(_: WCSession, didReceiveMessage: , replyHandler:)
から受け取ることができます。受信したデータは[String : Any]
型になっているので送信したキーから値を取り出し、適切な型にキャストすることで中身を取得することができます。replyHandler
で受け取ったデータを返すことで送信側に受信したことを知らせることができます。
replyHandlerにnilを渡すとデリケートメソッドが変化
引数replyHandler
にはnil
を渡すことも可能です。その場合は受信するデリゲートメソッドが変化するので注意してください。
送信処理の実装例
受信処理の実装例
受信側はsession(_: WCSession, didReceiveMessage:)
から受け取ることができます。
watchOS側から送信するとiOSがバックグラウンドで起動?
WatchKit 拡張機能がアクティブで実行中にこのメソッドを呼び出すと、対応する iOS アプリがバックグラウンドで起動され、アクセス可能になります。 iOS アプリからこのメソッドを呼び出しても、対応する WatchKit 拡張機能は起動されません。
公式ドキュメントには上記のように記述されていました。動作を確認してみたところ、iOS側が停止している状態でもwatchOS側からsendMessage
を送信するとreplyHandler
には受信が成功した通知が取得できました。
transferUserInfo
transferUserInfo
もペアリングされたデバイスに辞書形式でデータを送信できるメソッドです。しかしsendMessage
とは異なりキューにデータをスタックしていき、相手が受信可能になっていれば送信する仕組みになっています。
そのため相手のデバイスが非アクティブ(停止している)状態でもデータの送信が可能(正確にはキューイング)になっており、相手がアクティブになったタイミングでデータが送信され始めるため、相手側はアクティブになったと同時にデータを受信することができます。
このメソッドには相手が受信したかどうかやエラーをハンドリングする手段がないのでデータを確実に一方的に送信したい場合などに活用することができます。連続で実行すればどんどんキューが溜まっていきアクティブになると順番通りに送信されていくようです。
送信処理の実装例
受信処理の実装例
受信側はsession(_:, didReceiveUserInfo:)
から受け取ることができます。
シミュレーターでは動作しない
またこのメソッドはシミュレーターでは動作確認することができないと公式に記述されているので実機を使用してテストする必要があるので注意してください。
updateApplicationContext
公式リファレンス:updateApplicationContextメソッド
updateApplicationContext
もペアリングされたデバイスに辞書形式でデータを送信できるメソッドです。transferUserInfo
と同じように相手がバックグラウンドなどの状態でもデータを送信することが可能になっています。
transferUserInfo
との違いはキューに蓄積せずに常に更新することです。連続で実行してもアクティブになった時に送信されるのは最後に送信したデータになります。
このメソッドには相手が受信したかどうかやエラーをハンドリングする手段がないのでデータを確実に一方的に送信したい場合などに活用することができます。連続で実行すればどんどんキューが溜まっていきアクティブになると順番通りに送信されていくようです。
またこのメソッドはシミュレーターでも正常に動作します。
送信処理の実装例
受信処理の実装例
受信側はsession(_:, didReceiveApplicationContext:)
から受け取ることができます。
transferFile
transferFile
は他の送信メソッドと異なりペアリングされたデバイスに指定されたファイルを送信できるメソッドです。非常に大きなデータを送信する際などに活用することができます。
こちらも相手がバックグラウンドでも送信が可能であり、transferUserInfo
と同じくキューに溜まっていく仕組みのようです。データが大きいためパフォーマンスと充電を考慮し配信速度が調整される場合があります。そのためoutstandingFileTransfers
プロパティから未配信のファイルを参照できるようになっています。
またこのメソッドもシミュレーターでは動作確認することができないと公式に記述されているので実機を使用してテストする必要があるので注意してください。
送信処理の実装例
受信処理の実装例
受信側はsession(_:, didReceive:)
から受け取ることができます。
各メソッドの違いとまとめ
- sendMessage・・・辞書形式でデータを送信/相手が基本アクティブ/非アクティブなら成功しない(watchOS→iOSは別)
- transferUserInfo・・・辞書形式でデータを送信/相手がアクティブでない場合キューにスタックされていく/アクティブになったら送信
- updateApplicationContext・・・辞書形式でデータを送信/相手がアクティブでない場合に更新して保管されていく/アクティブになったら送信
- transferFile・・・ファイルを送信/相手がアクティブでない場合キューにスタックされていく/アクティブになったら送信
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。