【Swift4】WatchConnectivityによるiOSアプリとwatchOSアプリのデータの送受信方法【Objective-C】【Xcode9】

2020年8月29日

iOSアプリとwatchOSアプリ間のデータのやりとりはwatchOS1まではAppGroupsの設定により、ファイルの共有やUserDefaultの共有が可能でしたが、watchOS2からはAppGroupsは使えなくなり、代わりにWatchConnectivityによるデータのやりとりにする必要があります。

今回はこのWatchConnectivityによるデータの送受信方法をやってみましょう。

WatchConnectivity

WatchConnectivityにはInteractive messagingBackground 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)