Watch Connectivityを使うことでApple WatchとiPhoneのAppがお互いにメッセージ(データ)をやりとりすることが出来るようになります. watchOSのメジャーバージョンが2になってから利用できるようになりました. ここではApple Watch AppからiPhone Appを操作するというシチュエーションでWatch Connectivityを利用する方法を記録します. この時のiPhone Appはバックグラウンドでも問題ありません(CapabilitiesタブのBackground ModesがOFFでも大丈夫です). 言語はSwift2.0を使います.
- WatchConnectivityフレームワークをimport
- ViewControllerにWCSessionDelegateを追加
- WCSessionが利用可能ならばセッションを準備する
- sendMessageでメッセージをやりとり!
フレームワークをimportする
Watch Connectivityは"WatchConnectivity"というフレームワークとして提供されています. Watch側の"InterfaceController.swift"とiPhone側の"ViewController.swift"両方にこのフレームワークをimportします. "WCSessionDelegate"の追記も忘れずに.
InterfaceController.swift
import WatchKit import Foundation import WatchConnectivity class ViewController: UIViewController, WCSessionDelegate { ...
ViewController.swift
import UIKit import WatchConnectivity class InterfaceController: WKInterfaceController, WCSessionDelegate { ...
WCSessionクラスで通信の準備をする
WCSessionクラスがWatch - iPhone間の通信を管理してくれます. まずはWCSessionが利用可能か否かを判定し,可能ならばWCSessionをセットアップします. Watch側はwillActivate内に,iPhone側はviewDidLoad内に次のコードを書き込むと良いでしょう. WCSession型のプロパティを用意しておくと便利です.
InterfaceController.swift
var session: WCSession? ... override func willActivate() { super.willActivate() if WCSession.isSupported() { session = WCSession.defaultSession() session!.delegate = self session!.activateSession() } } ...
ViewController.swift
var session: WCSession? ... override func viewDidLoad() { super.viewDidLoad() if WCSession.isSupported() { session = WCSession.defaultSession() session!.delegate = self session!.activateSession() } } ...
メッセージを送る!
WCSessionの準備が出来たら後はメッセージを送るだけです. Watch App側(送り手側)はWCSessionのメソッド"sendMessage"でメッセージを送ります. iPhone App側(受け手側)はWCSessionDelegateのメソッド"session"で受信します. Watch Connectivityはメッセージを送れるだけではなく,返信を返すことも出来ます. 返信の処理はreplyHandlerというハンドラーで行います.
ここではシンプルにするため,Watch App側にボタン(UIButton)をひとつ用意します. このボタンがタップされたらメッセージを送信するようにします. ラベル(UILabel)も用意して,iPhoneからの返信内容を表示するようにしましょう. iPhone App側はラベル(UILabel)をひとつ用意して,Watchからのメッセージを表示します.
コードは次のとおりです. まずはUILabelのアウトレットを用意します. そしてWatch側のみUIButtonのアクションも用意します. 定数"message"と"reply"はディクショナリ,すなわち連想配列です. これが実際に送られるメッセージの本体になります. ["キー": 値]の形ですが,キーの部分はお好みの文字列にします. 受け手側が値を取り出す時のキーになるので,分かりやすい文字列が良いです. 値はAnyObject型なので文字通りどんなオブジェクトでも良いです. 今回はメッセージのやりとりという意味を込めて文字列にしました.
上から順に説明を. Watch AppのボタンがタップされたらWCSessionが準備されているかチェックします. 準備されていれば先へ進みます. メッセージ本体である定数"message"です. キーには"body",値には"From Watch App"と書きました. WCSessionのメソッド"sendMessage:replyHandler:errorHandler:"を使って定数"message"をiPhone側へ送ります. ハンドラ"replyHandler"には返信を受け取った後の処理を書きます. 今回はiPhoneからの返信であるディクショナリ"responses"の値をラベルへセットしています. クロージャ内なのでselfをつけ忘れないよう注意しましょう.
iPhone側はWCSessionDelegateのメソッド"session:didReceiveMessage:replyHandler:"でメッセージを受信します. まずはじめにメッセージの値をString型で取り出そうとしています. 上手く取り出せれば先へ進めます. ここであまりお目にかかれない函数を使います. dispatch_asyncです. 詳細は理解していませんが,この函数のおかげでキューの処理を非同期に実行してくれるようです. これが無いと画面の更新に時間がかかります. 定数"reply"に返信ディクショナリを用意します. replyHandlerに返信ディクショナリを渡せば返信は完了です. この返信を受け取ったWatch側はreplyHandlerの処理を実行します. つまりラベルの文字を返信"Reply from iPhone"にセットするはずです.
InterfaceController.swift
@IBAction func sendButtonTapped() { guard session != nil else { return } let message = ["body": "From Watch App"] session!.sendMessage(message, replyHandler: {(responses) -> Void in if let answer = responses["answer"] as? String { self.label.setText(answer) } }, errorHandler: {(error) -> Void in print(error) }) } ...
ViewController.swift
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { guard let message = message["body"] as? String else { return } dispatch_async(dispatch_get_main_queue()) { self.label.text = message } let reply = ["answer": "Reply from iPhone"] replyHandler(reply) } ...
iPhone側はWCSessionDelegateのメソッド"session:didReceiveMessage:replyHandler:"でメッセージを受信します. まずはじめにメッセージの値をString型で取り出そうとしています. 上手く取り出せれば先へ進めます. ここであまりお目にかかれない函数を使います. dispatch_asyncです. 詳細は理解していませんが,この函数のおかげでキューの処理を非同期に実行してくれるようです. これが無いと画面の更新に時間がかかります. 定数"reply"に返信ディクショナリを用意します. replyHandlerに返信ディクショナリを渡せば返信は完了です. この返信を受け取ったWatch側はreplyHandlerの処理を実行します. つまりラベルの文字を返信"Reply from iPhone"にセットするはずです.
Appを試す
コードをビルドし,iPhoneとWatchの両方にインストールしたら両方起動してUIを確認しましょう. Watch Appのボタンを押すと,まずiPhoneに"From Watch App"の文字が現れ,続けてWatchに"Reply from iPhone"の文字が表示されるはずです.
見事,Watch Connectivityによるメッセージのやりとりに成功しました! iPhone側のsessionメソッド内でiPhoneのデータを読み出す処理を呼び出し返信にそのデータを送れば,WatchからiPhoneのデータを読み出すことも可能です. 先にも書いたようにこのWatch ConnectivityはiPhone Appがバックグラウンドでも動作するので,iPhoneはポケットの中でもWatchのボタンを押せば返信を受け取ることが出来ます. もちろん次回iPhone Appを立ち上げた時には受信した証拠がちゃんと表示されます. 今回はWatchからiPhoneへの送信を例に紹介しましたが,iPhoneからWatchへの送信も同様の手順で実装できます. iPhone側でsendMessageし,Watch側のsessionで受信する,という全く同じ流れです.
9198570280932029721
https://www.storange.jp/2016/03/watch-connectivity.html
https://www.storange.jp/2016/03/watch-connectivity.html
Watch Connectivity
2016-03-25T21:59:00+09:00
https://www.storange.jp/2016/03/watch-connectivity.html
Hideyuki Tabata
Hideyuki Tabata
200
200
72
72