【Swift4】WatchConnectivityによるiOSアプリとwatchOSアプリのデータの送受信方法【Objective-C】【Xcode9】
iOSアプリとwatchOSアプリ間のデータのやりとりはwatchOS1まではAppGroupsの設定により、ファイルの共有やUserDefaultの共有が可能でしたが、watchOS2からはAppGroupsは使えなくなり、代わりにWatchConnectivityによるデータのやりとりにする必要があります。
今回はこのWatchConnectivityによるデータの送受信方法をやってみましょう。
WatchConnectivity
WatchConnectivityにはInteractive messagingとBackground transfersの二種類が存在します。
Interactive messagingの特徴
- データは即座に転送される
- iOSアプリ、watchOSアプリ間の通信が可能状態である(reachable)
Background transfersの特徴
- すぐにデータが転送されるわけではない
- 転送のタイミングはOSがいいかんじに決めてくれる
- 複数のデータを転送した場合、キューイングされ順に処理される
Session - データの受け取り準備
データを受け取る側は、受け取るための準備が必要です。
下記のコードに加え送信側が使用するメソッドに合わせて、受け取り用のDelegateメソッドも実装することになります。
Objective-C
if ([WCSession isSupported]) {
WCSession *wcSession = [WCSession defaultSession];
wcSession.delegate = self;
[wcSession activateSession];
}
Swift4.0
if (WCSession.isSupported()) {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
Interactive messaging - データのリアルタイム送信
- リアルタイムなデータの送受信が可能
- iPhoneとWatchがペアリングされている必要がある
Objective-C
送信側
NSDictionary *message = @{ @"test" : @"テストだよ" };
[[WCSession defaultSession] sendMessage:message
replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage) {
// リプライ受け取り後の処理
}
errorHandler:^(NSError * _Nonnull error) {
// エラー
}];
受信側
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message replyHandler:(void(^)(NSDictionary<NSString *, id> *replyMessage))replyHandler {
NSDictionary *reply = @{ @"test" : @"受け取ったよ" };
replyHandler(reply);
}
Swift4.0
送信側
WCSession.defaultSession().sendMessage(applicationDict,
replyHandler: { ([String : AnyObject]) -> Void in
// リプライ
})
errorHandler: { (NSError) -> Void in
// エラー
});
受信側
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
// 処理
}
Background transfers - データのキューイング送信
Background transfersには次の3つの転送方法が存在します。
1.Application Context
- 転送するデータはキューイングされ、送信待ちとなる
- 新しいデータがキューイングに追加されると古いデータは上書きされる
- 最終的に最新のデータのみが転送される
Objective-C
送信側
NSDictionary *context = @{ @"test" : @"テストだよ" };
[[WCSession defaultSession] updateApplicationContext:context
error:nil];
受信側
- (void)session:(WCSession *)session didReceiveApplicationContext:(NSDictionary<NSString *,id> *)applicationContext {
// 処理
}
Swift4.0
送信側
do {
let context = ["test" : "テストだよ"]
try WCSession.defaultSession().updateApplicationContext(context)
} catch {
// エラー
}
受信側
func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) {
// 処理
}
2.User Info Transfer
- Application Contextとは違い、キューイングされたデータは上書きされない
- すべてのデータを転送することができる
Objective-C
送信側
NSDictionary *context = @{ @"test" : @"テストだよ" };
[[WCSession defaultSession] transferUserInfo:context];
受信側
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo {
// 処理
}
Swift4.0
送信側
let userInfo = ["test" : "テストだよ"]
let transfer = WCSession.defaultSession().transferUserInfo(userInfo)
受信側
func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
// 処理
}
3.File Transfer
- ファイルの転送が可能
Objective-C
送信側
NSURL *url = [NSURL URLWithString:@"~~~"];
NSDictionary *metadata = @{ @"test" : @"テストだよ" };
[[WCSession defaultSession] transferFile:url metadata:metadata];
受信側
- (void)session:(WCSession *)session didReceiveFile:(WCSessionFile *)file {
// 処理
}
Swift4.0
送信側
let url = // ファイルのURL
let data = // ファイル情報
let fileTransfer = WCSession.defaultSession().transferFile(url, metadata:data)
受信側
func session(session: WCSession, didReceiveFile file: WCSessionFile) {
// 処理
}
転送サイズについて
sendMessage:65,536 bytes (65.5 KB)
transferUserInfo:65,536 bytes (65.5 KB)
applicationContext:262,144 bytes (262.1 KB)