2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-03-17

#記事一覧
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)

    ```swift:ViewController.swift:sessionDidBecomeInactiveの実装
    public func sessionDidBecomeInactive(_ session: WCSession){
        print("sessionDidBecomeInactive")
    }
    ```

* public func sessionDidDeactivate(_ session: WCSession)

    ```swift:ViewController.swift:sessionDidDeactivateの実装
    public func sessionDidDeactivate(_ session: WCSession){
        print("sessionDidDeactivate")
    }
    ```

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

* [updateApplicationContext(_:)](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615621-updateapplicationcontext)
* [sendMessage(_:replyHandler:errorHandler:)](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615687-sendmessage)
* [sendMessageData(_:replyHandler:errorHandler:)](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615617-sendmessagedata)
* [transferUserInfo(_:)](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615671-transferuserinfo)
* [transferFile(_:metadata:)](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615667-transferfile)
* [transferCurrentComplicationUserInfo(_:)](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615639-transfercurrentcomplicationuseri)

今回はsendMessageでデータを送信する。
[Swift MkMapViewで地図アプリ作成してみた(10)](https://qiita.com/rain_00_00_09/items/d426a32ab8356a97fc78)で取得した緯度経度をsendMessageで送信する。

```swift: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

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?