【Swift/Apple Watch】通信可能(ペアリング)状態を観測/取得する方法!isReachableの変化
この記事からわかること
- SwiftでApple Watchアプリを開発する方法
- iOSとwatchOSが通信可能状態であることを取得/観測するには?
- WCSessionのisReachableプロパティの使い方
- WCSession counterpart app not installedとは?
- WCSessionDelegateドのsessionReachabilityDidChangeメソッドの役割
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- iOS:17.0
- watchOS:10.0
- Swift:5.9
- macOS:Sonoma 14.1
iOS↔︎watchOS間が通信可能状態であることを取得する方法
iOSアプリと連携した機能を実装しているwatchOSのアプリで両者がBluetoothでペアリングし通信可能状態であることをコードから取得するにはWCSession
クラスのisReachable
プロパティを参照します。
WCSession.default.isReachable // true or false
isReachable
プロパティは正確にはアプリ同士がメッセージの送受信が利用できるかどうかを示す真偽値を返します。なのでこちらは両者のアプリが通信可能状態にあるかないかを識別する際に利用します。
ペアリングしているかを識別する
iPhoneとApple Watch自体がペアリング状態にあるかを取得したい場合はWCSession
クラスのisPaired
プロパティを参照します。
WCSession.default.isPaired // true or false
こちらはアプリではなく、デバイス同士が接続されていかを識別する際に利用します。
通信可能状態の変化を観測する
通信可能状態の変化を観測したい場合はWCSessionDelegate
のsessionReachabilityDidChange(_:)
メソッドが変化した際に呼ばれるデリゲートメソッドです。例えばiOS側でwatchOS側と接続するためのクラスを実装していた場合は以下のようになります。
class WatchConnectViewModel: NSObject {
override init() {
self.session = .default
super.init()
if WCSession.isSupported() {
self.session.delegate = self
self.session.activate()
}
}
func sessionReachabilityDidChange(_ session: WCSession) {
print("状態が変化したよ")
let isReachable = session.isReachable
if isReachable {
print("通信可能状態になりました")
} else {
print("通信が不可能な状態になりました")
}
}
}
ですがこのsessionReachabilityDidChange(_:)
メソッドはiOSアプリを起動させたタイミングでは呼ばれず、watchOSアプリが停止した場合や再度復帰した場合に呼ばれるようです。呼ばれるタイミングは以下のような感じ
// watchOSアプリ起動
・・・呼ばれない
// iOSアプリ起動
・・・呼ばれない
[ペアリング/通信可能状態]
// watchOSアプリが停止
状態が変化したよ
通信が不可能な状態になりました
// watchOSアプリが再開
状態が変化したよ
通信可能状態になりました
通信状態に応じてUIを更新したい場合
通信可能状態をリアルタイムで観測しUIなどに反映させたい場合はObservableObject
を使って以下のように実装するのが良いのかも?しれません。isReachable
の初回の更新はsession(_:,activationDidCompleteWith:, error:)
メソッドでアクティベートになっているかを識別できるのでここで格納しています。
class WatchConnectViewModel: NSObject, ObservableObject {
var session: WCSession
@Published var isReachable = false
override init() {
self.session = .default
super.init()
if WCSession.isSupported() {
self.session.delegate = self
self.session.activate()
}
}
}
extension WatchConnectViewModel: WCSessionDelegate {
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
if let error = error {
print(error.localizedDescription)
} else {
print("セッション:アクティベート")
isReachable = session.isReachable // true
}
}
func sessionReachabilityDidChange(_ session: WCSession) {
print("変化したよ")
isReachable = session.isReachable
if isReachable {
print("通信可能")
} else {
print("通信が切断")
}
}
func sessionDidBecomeInactive(_ session: WCSession) { }
func sessionDidDeactivate(_ session: WCSession) { }
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。