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

Swift MkMapViewで地図アプリ作成してみた(16)- iOSから転送された地点から現在位置の距離をwatchOSで計算して表示する

記事一覧

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

iOSのアプリから取得した緯度経度を保持する

iOSのアプリでロングタップした位置をwatchOSに送信する

sendMessageでwatchOSにロングタップした位置を送信する方法は以下の記事を参照ください。

受信した緯度経度を保持する

クラスのメンバ変数に緯度経度を追加し、iOSからsendMessageで送信された緯度経度を変数に設定する。

InterfaceController.swift:緯度経度の変数を追加
class InterfaceController:  WKInterfaceController,
                            WCSessionDelegate { // sasaki
    var dlon:Double! = 0
    var dlat:Double! = 0
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
        }

        // iOSからsendMessageで送信された緯度経度を変数に設定
        dlon = lon
        dlat = lat
    }

CLLocationManagerで現在位置を取得する

CLLocationManagerのdelegateを登録する

CoreLocationをimportし、CLLocationManagerDelegateを継承する。
現在位置取得に必要なCLLocationManagerの変数を定義する。

InterfaceController.swift
import CoreLocation

class InterfaceController:  WKInterfaceController,
                            WCSessionDelegate,
                            CLLocationManagerDelegate {
    var dlon:Double! = 0
    var dlat:Double! = 0
    var locationManager = CLLocationManager()

Initializerメソッドで、CLLocationManagerのdelegateを登録する。

InterfaceController.swift
    override init() {
        super.init()

        // CLLocationManagerのdelegateを登録
        locationManager.delegate = self
    }

CLLocationManagerで現在位置の更新を受信する

以下の条件を満たしている場合に、startUpdatingLocationメソッドで現在位置の更新を開始できる。

  • locationServicesEnabledメソッドで端末の位置情報サービスが有効である
  • authorizationStatusメソッドでユーザから位置情報利用の許可を一度得ている
InterfaceController.swift
    override init() {
        super.init()

        // CLLocationManagerのdelegateを登録
        locationManager.delegate = self

        // 端末の位置情報サービスが有効である
        if CLLocationManager.locationServicesEnabled() {
            switch CLLocationManager.authorizationStatus() {
            // ユーザから位置情報利用の許可を一度得ている
            case .authorizedAlways, .authorizedWhenInUse:
                // 現在位置の更新を開始
                locationManager.startUpdatingLocation()
            case .notDetermined:
                print("notDetermined")
            case .restricted:
                print("restricted")
            case .denied:
                print("denied")
            }
        }
    }

locationManagerメソッドを定義すると、現在位置の更新を受信できる。

InterfaceController.swift
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        print(Date(), locations)
    }

現在位置更新を受信した時にiOSから受信した位置との距離を表示する

2点間の距離(m)を算出するメソッドを作成する

引数に現在位置を指定して、クラスのメンバ変数に設定したiOSから受信した緯度経度との距離(m)を算出するメソッドを作成する。

InterfaceController.swift
    func calcDistance(_ a: CLLocationCoordinate2D) -> CLLocationDistance {
        // CLLocationオブジェクトを生成
        let aLoc: CLLocation = CLLocation(latitude: a.latitude, longitude: a.longitude)
        let cloclon:CLLocationDegrees = CLLocationDegrees(exactly: dlon)!
        let cloclat:CLLocationDegrees = CLLocationDegrees(exactly: dlat)!
        let bLoc: CLLocation = CLLocation(latitude: cloclat, longitude: cloclon)
        // CLLocationオブジェクトのdistanceで2点間の距離(m)を算出
        let dist = bLoc.distance(from: aLoc)
        return dist
    }

現在位置の更新を受信した時に距離を算出してwatchOSのアプリに表示する

locationManagerメソッドで現在位置の更新を受信した時に、iOSから受信した緯度経度との距離(m)を算出して表示する。

InterfaceController.swift
    // CLLocationManagerのdelegate:現在位置更新
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        print(Date(), locations)

        // iOSから緯度経度を受信している場合
        if dlon != 0 && dlat != 0 {
            // 現在位置とiOSから受信した緯度経度との距離(m)を算出する
            let distance = calcDistance((locations.last?.coordinate)!)
            // mをyardに変換する
            let yardStr = Int(distance * 1.09361)
            // 距離をラベルのテキストに設定する
            let fontSize = UIFont.systemFont(ofSize: 45)
            let text = String(Int(distance).description + "m" + "\n" + yardStr.description + "y")
            let attrStr = NSAttributedString(string: text, attributes:[NSAttributedString.Key.font:fontSize])
            label.setAttributedText(attrStr)
        }
    }

iOSから緯度経度を受信した時にも現在位置との距離を表示する

現在位置をクラスのメンバ変数に保持する

メンバ変数をCLLocationCoordinate2D型で定義する。

InterfaceController.swift
class InterfaceController:  WKInterfaceController,
                            WCSessionDelegate,
                            CLLocationManagerDelegate {
    var locCord2D:CLLocationCoordinate2D?

現在位置をクラスのメンバ変数に保持する。

InterfaceController.swift
    // CLLocationManagerのdelegate:現在位置更新
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print(Date(), locations)

        // 現在位置をクラスのメンバ変数に保持する
        locCord2D = (locations.last?.coordinate)!

        // iOSから緯度経度を受信している場合
        if dlon != 0 && dlat != 0 {

iOSから緯度経度を受信した時にも現在位置との距離を表示する

sessionメソッドに距離を表示する処理を追加する。

InterfaceController.swift
    // 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
        }

        // iOSからsendMessageで送信された緯度経度を変数に設定
        dlon = lon
        dlat = lat

        // iOSから緯度経度を受信した時にも現在位置との距離を表示する
        if nil != locCord2D {
            // 現在位置とiOSから受信した緯度経度との距離(m)を算出する
            let distance = calcDistance(locCord2D!)
            // mをyardに変換する
            let yardStr = Int(distance * 1.09361)
            // 距離をラベルのテキストに設定する
            let fontSize = UIFont.systemFont(ofSize: 45)
            let text = String(Int(distance).description + "m" + "\n" + yardStr.description + "y")
            let attrStr = NSAttributedString(string: text, attributes:[NSAttributedString.Key.font:fontSize])
            label.setAttributedText(attrStr)
        }
    }

image1.png

記事一覧

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

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
ユーザーは見つかりませんでした