Help us understand the problem. What is going on with this article?

Swift MkMapViewで地図アプリ作成してみた(14)- 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で地図アプリ作成してみた(10)で取得した緯度経度を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

yuta-sasaki
車載ソフトウェア開発者です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした