[Swift]現在地から目的地までの2地点の最短経路を表示・削除する方法
mapView上に線を描画する手法、特に、地図上の現在地から目的地までの最短ルートを地図上に表示する方法について書きます。
なお、概ね、Qiitaのswiftで現在地と目的地を結ぶ経路を地図に表示するを参考にさせていただきましたが、最新版のXcodeに対応するように修正しました。
さらに、削除方法についても記述します。
XcodeはVersion 8.3.1 を使っています。
swiftのバージョンはversion 3.1です。
Contents
地図上のピンをタップして座標を取得する方法
さて、まずは適当な位置にアノテーションを立てることを行います。
具体的には、私は中野区の公園とか児童館とかそういった住所を東京都中野区の公式ホームページから取得して全部座標変換し、地図上にアノテーションで一覧表示しました。
その後、そのアノテーション(ピン)をタップすると、その座標を取得します。
//アノテーションがタップされると行う処理 func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { //アノテーションの緯度と経度を取得 self.destLocation = CLLocationCoordinate2D(latitude: annotation!.coordinate.latitude,longitude: annotation!.coordinate.longitude) // 現在地の取得を開始 self.locationManager.startUpdatingLocation() // 現在地から目的地への経路を検索 getRoute() }
これはピンがタップされると行われるメソッド。
最初の行で、そのピンの緯度と経度を取得します。
次に現在地の座標を取得。
そして、上記リンク先で使われていた「getRoute()」メソッドを呼び出します。
swiftでpolylineを削除する方法
あとはほぼ、上記リンク先で紹介されている内容とほぼ同じなのですが、注意したいのは、すでに表示されている経路を地図上から削除することです。
そうしないと、アノテーションを押すたびに線が地図上に追記されていき、何がなんだかよくわからなくなります。
こうなる。
だから、新しいピンが押されるたびに、古い経路は削除する必要があります。
//経路情報を取得 func getRoute() { //地図上からpolylineを消す self.mapView.removeOverlays(mapView.overlays) ・・・ }
mapView.removeOverlays(mapView.overlays)を記述することで、現在表示されている地図上のルート情報を全てリセットすることができます。
候補の経路を全て表示する
ところで、上記リンク先では、ルートを表示するときに、以下のようにしています。
var route: MKRoute = response.routes[0] as MKRoute
// 経路を描画
self.mapView.addOverlay(route.polyline!)
この最初の行によれば、複数の候補ルートの中から1つだけをrouteとして取得しているように見えました。
だから私は、候補ルートを全部表示させてみたらどうなるのだろうかと考えて、以下のようにしてみました。
for route in response!.routes{ // 経路を描画 self.mapView.add(route.polyline) }
こうすると、現在地から目的地までのいろんな候補ルートが複数表示されるのかなと思いまして。
しかしどうやっても1本の経路しか表示されないので、最初から最短ルート1本にしぼられるんでしょうなあ。
この辺り、よく理解してません。
あと、現状での最新バージョンのxcode,swiftだと、「self.mapView.addOverlay(route.polyline!)」じゃなくて「self.mapView.add(route.polyline!)」のように、addだけにすべきのようです。
線を描画する際に呼ばれるべきデリゲートメソッドが呼ばれない場合
self.mapView.add(overlay: MKOverlay, level: MKOverlayLevel)とかを使った際に、「func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {}」のデリゲートメソッドが呼ばれると思うのですが、これが呼ばれずに描画がされないという事態が続きました。
このエラーというか不具合はなんなのかなあと思って3日くらい困っていたのですが、簡単に解決しました。
func mapView(_ mapView: MKMapView!, rendererFor overlay: MKOverlay!) -> MKOverlayRenderer! {
mapView: MKMapView!の前にアンダーバーとスペースを入れるだけで解決しました。
Xcodeからそう直すようにずっとサジェスト受けてたのに気づきませんでした。
サジェストには素直に耳を傾けた方がいいですね。