【Swift】MKMapViewでルート検索を実装してみた

前々から実装しようと思っていたルート検索機能を実装してみました。

目的地と現在地の座標さえ分かれば実装できます。

作ってみたアプリはこんな感じ。

目的地のピンをタップして、経路ボタンを押すとルートが表示されるようにしました。

所要時間がトーストで表示されるようにしました。

コードは以下の通り。

 func showRoute(dest: CLLocation) {
        let sourcePlaceMark = MKPlacemark(coordinate: currentLocation.coordinate)
        let destinationPlaceMark = MKPlacemark(coordinate: dest.coordinate)
          
        let directionRequest = MKDirections.Request()
        directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
        directionRequest.destination = MKMapItem(placemark: destinationPlaceMark)
        directionRequest.transportType = .walking

        let directions = MKDirections(request: directionRequest)
        directions.calculate { (response, error) in
        guard let directionResonse = response else {
            if let error = error {
                    print("we have error getting directions==\(error.localizedDescription)")
            }
                return
            }
            let route = directionResonse.routes[0]
            self.route = route
            self.dispMap.addOverlay(route.polyline, level: .aboveRoads)
            let time = route.expectedTravelTime / 60
            self.showToast(message: "所要時間は「" + String(time.rounded()) + "」分です。", font: .systemFont(ofSize: 12.0))
           }
    }

ルート検索した時に縮尺を変える処理が参考記事には書いてありましたが、縮尺変更は使いづらかったので消しました。

`MKDirections`を使ってリクエストを投げるとAppleのサーバから目的までのルート情報が手に入ります。

`polyline`が目的地までのルートを表示する線です。

この線を青色で描画するためにmapViewに以下のレンダラーを追加します。

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let renderer = MKPolylineRenderer(overlay: overlay)
        renderer.strokeColor = UIColor.blue
        renderer.lineWidth = 4.0
        return renderer
    }

ちなみにこのレンダラーを追加したら、エミュレータで以下のエラーが出るようになりました。

Compiler error: Invalid library file

Xcodeのバグのようです。。。

実機だと出ないのですけどね。

polylineは一度書くとずっと残り続けるのでどこかのタイミングでremoveする必要があります。

ピン選択が解除された時に、経路線も削除するようにしました。

    //ピンが選択解除された時に呼ばれる
    func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
        if self.route != nil{
            self.dispMap.removeOverlay(self.route.polyline)
        }
    }

参考

https://qiita.com/entaku0818/items/8ba9065c0074dcfb0ea7

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog