WatchConnectivityでApple Watchとデータ連携してみて分かったこと

WatchConnectivityでApple Watchとデータ連携してみて分かったこと 学習記録

Core Dataでデータを永続化する実装を終えたところで、以前から興味のあったApple Watch連携に挑戦し、WatchConnectivityによるiPhoneとのデータ送受信を試してみました。

1. セッションを有効化しなくても通信できると思っていた

最初、他の多くのフレームワークと同様に、インスタンスを作るだけで通信できるものだと思い込んでいました。

let session = WCSession.default
session.sendMessage(["key": "value"], replyHandler: nil)

このコードを実行してもメッセージが届かず、コンソールに警告が出るだけでした。調べてみると、WCSessionは使用前にdelegateを設定した上でactivate()を呼び出し、セッションを有効化しておく必要がある仕組みだと分かりました。

2. sendMessageとtransferUserInfoの違いを理解せず混乱した

セッションを有効化した後、送信方法にも複数の種類があることに気づき、最初はどれを使えばよいのか混乱しました。

違い:
sendMessage は両端末が起動中でないと届かない即時送信
transferUserInfo は後からでも届くキュー式の送信

sendMessageは相手のアプリがアクティブな状態でないと失敗するのに対し、transferUserInfoはキューに積まれ、相手のアプリが後で起動した際にも配信される仕組みだと分かりました。用途に応じてこの2つを使い分ける必要がありました。

3. Watchアプリが未起動のときにデータが届かず戸惑った

transferUserInfoを使ってデータを送っても、Watch側のアプリを一度も起動していない場合はデータが届かないという状況に遭遇しました。

確認したこと:
Watchアプリが少なくとも一度アクティブ化される必要がある

送信データ自体はシステム側でキューイングされるものの、受信側のセッションが一度も有効化されていない状態では処理されないと分かりました。Watchアプリを初回起動した時点でセッションを有効化する処理を必ず入れておく必要がありました。

4. iPhone側とWatch側で同じコードを共有できると誤解していた

セッションの有効化やデリゲートの実装を、iPhone側とWatch側で同じクラスにまとめようとして、うまくビルドできませんでした。

#if os(watchOS)
import WatchKit
#else
import UIKit
#endif

WatchConnectivityの基本的なAPI自体は共通ですが、周辺のフレームワーク(UIKitとWatchKitなど)が異なるため、完全に同じコードをそのまま両方のターゲットで使うことはできないと理解しました。条件付きコンパイルを使って差分を吸収する必要がありました。

まとめ

  • WCSessionはactivate()を呼んでセッションを有効化してからでないと使えない
  • sendMessageは即時性が高いが両端末起動中限定、transferUserInfoは後から届くキュー式という違いがある
  • Watch側のセッションが一度も有効化されていないと、キューに積んだデータも届かない
  • iPhone側とWatch側で完全に同じコードは共有できず、条件付きコンパイルでの差分吸収が必要

普段あまり意識しない「2つの端末間の通信」という特性上、単体のフレームワークよりも状態管理を丁寧に考える必要があると実感した実装でした。


本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。

コメント

タイトルとURLをコピーしました