【Swift】MKMapItemの使い方。目的地までの経路をマップアプリで検索する。(Swift 2.1、XCode 7.2)
目的地の場所が分かったあとに知りたいこと
前回までの記事で現在地や目的地にピンを刺す方法を説明してきた。⇒「記事」
目的地の場所が分かったあとに必要な情報といえば「目的地までどのように行けば辿り着けるか。その所要時間はどのくらいか。」だ。そこで本記事では、現在位置からピンを刺した位置までの経路をマップアプリを用いて検索する方法を説明する。
以降の手順は「Map Kit Viewの使い方」の続きから行うので、実装を試してみる人は先に読んでおくことをお勧めする。
現在地を把握する機能を実装する
下図赤枠のinfo.plistをクリックしてプロパティ一覧を表示する。一覧にマウスカーソルを持っていくと下図黄緑枠の「+」ボタンが表示されるので押す。
Keyに「NSLocationWhenInUseUsageDescription」、Typeに「String」、Valueに「現在位置を地図に表示するために利用します。」を入力する。これは、位置情報サービスの設定項目に「このAppの使用中のみ許可」を追加するための設定である。
ストーリーボードに戻り、マップビューをクリックして選択する。下図赤枠のアトリビュートインスペクタボタンを押して設定画面を開き、User Locationにチェックを入れる。これはマップにユーザーの現在位置を点灯させるための設定である。
ViewController.swiftを以下のコードに変更する。起動時に現在位置を取得して地図の中心座標を現在位置に設定している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
// // ViewController.swift // import UIKit import MapKit class ViewController: UIViewController, CLLocationManagerDelegate { @IBOutlet weak var testMapView: MKMapView! var testManager:CLLocationManager = CLLocationManager() //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() //デリゲート先を自分に設定する。 testManager.delegate = self //位置情報の利用許可を変更する画面をポップアップ表示する。 testManager.requestWhenInUseAuthorization() //位置情報の取得を要求する。 testManager.requestLocation() } //位置情報取得時の呼び出しメソッド func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){ for location in locations { //現在位置をマップの中心にして登録する。 let center = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude) let span = MKCoordinateSpanMake(0.05, 0.05) let region = MKCoordinateRegionMake(center, span) testMapView.setRegion(region, animated:true) } } //位置情報取得失敗時の呼び出しメソッド func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { print(error) } } |
この時点で動作確認をしておこう。以下は実際のプレイ動画。現在位置を中心とした地図が表示され、現在位置が点滅している。
マップアプリを使って経路を検索する機能を実装する。
次に、地図を長押しした座標にピンが刺さり、ピンの吹き出しにあるボタンを押すとマップアプリが起動する動きを実装する。
Long Press Gesture Recognizerをマップビューに配置する(下図赤矢印)。部品一覧に下図黄緑枠のジェスチャーリコグナイザーが追加される。
紫枠のアシスタントエディタボタンを押してViewController.swiftを開く。Ctrlキーを押しながらジェスチャーリコグナイザーをドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示する(青矢印)。
Connectionに「Action」、Nameに「pressMap」、Typeに「UILongPressGestureRecognizer」を入力し、Connectボタンを押す。これで長押しのイベントをソースコードで受けれるようになった。
ViewController.swiftを以下のコードに変更する。
地図が長押しされたらその座標にピンを刺している。ピンの吹き出しには経路ボタンがあり、ボタンが押されたらマップアプリを起動する。
オプションは「車で移動」、「ハイブリッド表示」で起動し、起動後に現在地から目的地までの経路の候補と所要時間が表示されるので、経路を選択して「出発」ボタンを押すと案内が開始する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
// // ViewController.swift // import UIKit import MapKit class ViewController: UIViewController, CLLocationManagerDelegate,MKMapViewDelegate{ @IBOutlet weak var testMapView: MKMapView! var testManager:CLLocationManager = CLLocationManager() //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() //デリゲート先を自分に設定する。 testMapView.delegate = self testManager.delegate = self //位置情報の利用許可を変更する画面をポップアップ表示する。 testManager.requestWhenInUseAuthorization() //位置情報の取得を要求する。 testManager.requestLocation() } //位置情報取得時の呼び出しメソッド func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){ for location in locations { //現在位置をマップの中心にする。 let center = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude) let span = MKCoordinateSpanMake(0.05, 0.05) let region = MKCoordinateRegionMake(center, span) testMapView.setRegion(region, animated:true) } } //位置情報取得失敗時の呼び出しメソッド func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { print(error) } //マップビュー長押し時の呼び出しメソッド @IBAction func pressMap(sender: UILongPressGestureRecognizer) { //マップビュー内のタップした位置を取得する。 let location:CGPoint = sender.locationInView(testMapView) if (sender.state == UIGestureRecognizerState.Ended){ //タップした位置を緯度、経度の座標に変換する。 let mapPoint:CLLocationCoordinate2D = testMapView.convertPoint(location, toCoordinateFromView: testMapView) //ピンを作成してマップビューに登録する。 let annotation = MKPointAnnotation() annotation.coordinate = CLLocationCoordinate2DMake(mapPoint.latitude, mapPoint.longitude) annotation.title = "目的地候補" annotation.subtitle = "ボタンタップで経路を表示" testMapView.addAnnotation(annotation) } } //アノテーションビューを返すメソッド func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { //現在位置の点滅がピンにならないように、アノテーションがUserLocationの場合は何もしないようにする。 if( annotation is MKUserLocation ) { return nil } //アノテーションビューを生成する。 let testView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: nil) //吹き出しを表示可能にする。 testView.canShowCallout = true //経路ボタンをアノテーションビューに追加する。 let button = UIButton() button.frame = CGRectMake(0,0,40,30) button.setTitle("経路", forState: .Normal) button.backgroundColor = UIColor.blueColor() button.setTitleColor(UIColor.whiteColor(), forState:.Highlighted) testView.rightCalloutAccessoryView = button return testView } //ボタン押下時の呼び出しメソッド func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { //マップアプリに渡す目的地の位置情報を作る。 let coordinate = CLLocationCoordinate2DMake(view.annotation!.coordinate.latitude, view.annotation!.coordinate.longitude) let placemark = MKPlacemark(coordinate:coordinate, addressDictionary:nil) let mapItem = MKMapItem(placemark: placemark) //起動オプション let option:[String:AnyObject] = [MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving, //車で移動 MKLaunchOptionsMapTypeKey : MKMapType.Hybrid.rawValue] //地図表示はハイブリッド //マップアプリを起動する。 mapItem.openInMapsWithLaunchOptions(option) } } |
以下は実際のプレイ動画。
下表は、起動オプションに設定できる項目の一覧。動作確認は1と2のみ実施⇒「公式リファレンス」
設定名 | 説明 | |
---|---|---|
1 | MKLaunchOptionsDirectionsModeKey | 目的地までの移動方法を車、徒歩、交通機関から選択する。 |
2 | MKLaunchOptionsMapTypeKey | マップの表示形式を標準、衛生、ハイブリット、SatelliteFlyover、HybridFlyoverから選択する。 |
3 | MKLaunchOptionsMapCenterKey | マップの中心座標を指定する。 |
4 | MKLaunchOptionsMapSpanKey | マップの表示範囲を指定する。 |
5 | MKLaunchOptionsShowsTrafficKey | 交通情報を表示するかをtrue、falseで設定する。 |
6 | MKLaunchOptionsCameraKey | 3Dカメラの位置、角度を設定する。 |