Edited at

Swift MkMapViewで地図アプリ作成してみた(12)- iOSから送信したデータをwatchOSで受信する


記事一覧

Swift MkMapViewで地図アプリ作成してみた(記事一覧)


iOSからwatchOSにデータを送信する


セッションをアクティブにする

iOSアプリとwatchOSアプリ間の通信に必要なWatchkitのWCSeesionオブジェクトを使用するため、WatchConnectivityをimportする。


ViewController.swift:

import WatchConnectivity


セッションをアクティブにするために、WCSessionDelegateを継承し、デフォルトのセッションオブジェクトにデリゲートを割り当て、activate()メソッドを呼び出す。


ViewController.swift:セッションをアクティブにする

class ViewController:   UIViewController,

CLLocationManagerDelegate,
UIGestureRecognizerDelegate,
WCSessionDelegate {

var session: WCSession!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

// セッションをアクティブにする
if (WCSession.isSupported()) {
self.session = WCSession.default
self.session.delegate = self
self.session.activate()
}


WCSessionDelegateに次の3つのメソッドを実装しないとエラーになる。



  • public func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?)


    ViewController.swift:sessionの実装

    // セッションアクティブ化の結果が通知される
    
    public func session(_ session: WCSession, activationDidCompleteWithactivationState:WCSessionActivationState, error: Error?){
    switch activationState {
    case .activated:
    print("セッションアクティブ")
    case .inactive:
    print("セッションはアクティブでデータ受信できる可能性はあるが、相手にはデータ送信できない")
    case .notActivated:
    print("セッション非アクティブで通信できない状態")
    let errStr = error?.localizedDescription.description
    print("error: " + (errStr?.description)!)
    }
    }

    errorは問題が発生したことを示すエラーオブジェクト。

    アクティブ化が正常に完了した場合はnilで、activationStateパラメーターが.notActivatedの場合、失敗の理由が格納される。

    breakは不要。なのは驚いた。。




  • public func sessionDidBecomeInactive(_ session: WCSession)


    ViewController.swift:sessionDidBecomeInactiveの実装

    public func sessionDidBecomeInactive(_ session: WCSession){
    
    print("sessionDidBecomeInactive")
    }




  • public func sessionDidDeactivate(_ session: WCSession)


    ViewController.swift:sessionDidDeactivateの実装

    public func sessionDidDeactivate(_ session: WCSession){
    
    print("sessionDidDeactivate")
    }




watchOSにデータを送信する

activationStateプロパティが.activatedに設定されている場合にのみ、以下のいずれかの方法でwatchOSのアプリにデータを送信できる。

今回はsendMessageでデータを送信する。

Swift MkMapViewで地図アプリ作成してみた(6)で取得した緯度経度をsendMessageで送信する。


ViewController.swift:watchOSに緯度経度を送信

// UILongPressGestureRecognizerのdelegate:ロングタップを検出する

@IBAction func mapViewDidLongPress(_ sender: UILongPressGestureRecognizer) {
// ロングタップ開始
if sender.state == .began {
// ロングタップ開始時に古いピンを削除する
mapView.removeAnnotation(pointAno)
}
// ロングタップ終了(手を離した)
else if sender.state == .ended {

//
// 処理は割愛、上記の[Swift MkMapViewで地図アプリ作成してみた(6)]をご参照ください。
//

// watchOSに緯度経度を送信
let dlon:Double = center.longitude
let dlat:Double = center.latitude
let contents = ["lon":dlon, "lat":dlat]
self.session.sendMessage(contents, replyHandler: { (replyMessage) -> Void in
print ("receive from apple watch");
}) { (error) -> Void in
print(error)
}



watchOSでiOSから送信されたデータを受信する


セッションをアクティブにする

iOSアプリとのセッションを確立するために、watchOS側のInterfaceController.swiftを実装する。


InterfaceController.swift:WatchConnectivityのimportとWCSessionDelegateの継承

import WatchConnectivity

class InterfaceController: WKInterfaceController,
WCSessionDelegate {


デフォルトのセッションオブジェクトにデリゲートを割り当て、activate()メソッドを呼び出す。

storyboardのlabelとコード上のlabelを紐付ける。


InterfaceController.swift:セッションをアクティブにする

class InterfaceController:  WKInterfaceController,

WCSessionDelegate {
var session:WCSession!
@IBOutlet weak var label: WKInterfaceLabel!

override func awake(withContext context: Any?) {
super.awake(withContext: context)

// Configure interface objects here.
if (WCSession.isSupported()) {
self.session = WCSession.default
self.session.delegate = self
self.session.activate()
}
}


WCSessionDelegateに次の1つのメソッドを実装しないとエラーになる。


  • func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {


InterfaceController.swift:sessionの実装

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {

print("session")
}


iOSからデータを受信する

iOSからsendMessageで送信されたデータを受信する。


InterfaceController.swift:iOSからsendMessageで送信されたデータを受信

    // iPhoneからMessage受信

public func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Swift.Void){
print("receiveMessage::\(message)")

guard let lon = message["lon"] as? Double else {
return
}

guard let lat = message["lat"] as? Double else {
return
}

label.setText("lon: " + lon.description + "\n" + "lat: " + lat.description)
}


実行すると以下の様になる。

image1.png


参考文書

WCSession - WatchConnectivity | Apple Developer Documentation