Swift Playgroundsで学ぶiOSプログラミング

マップにピンを立てて経路検索するプログラミング

文●柴田文彦 編集●吉田ヒロ

2017年05月08日 17時00分

緯度と経度を指定してピンを打つ

 今回のプログラムは、前回作成したものに書き加える形で始めます。ざっと前回の復習をしておきましょう。まずマップビュー(MKMapView)のオブジェクトを作成し、適当に位置とタイプを指定し、それを標準的なビューコントローラーのビューに設定し、そのビューコントローラーをプレイグラウンドのライブビューとして張り付けるというものでした。

 今回は、まずアノテーションを付けるということがどういうことなのかを理解するため、もっとも単純なアノテーション、虫ピンのようなピンを地図上に立てることから始めます。そのための記述を、前回のプログラムの上に追加してみましょう。これなら、独自のビューコントローラーを作らずに実現できます。

 ポイントアノテーション(MKPointAnnotation)オブジェクトを作成し、その位置を設定し、それをマップビューに追加(addAnnotation)すればよいのです。その部分のコードは以下のようになります。

let ano = MKPointAnnotation()
ano.coordinate = CLLocationCoordinate2D(latitude: 35.6984, longitude: 139.7456)
mapView.addAnnotation(ano)

 ピンの位置は、CLLocationCoordinate2Dというオブジェクトによって指定します。これは、いわば2次元の座標ですが、緯度と経度で指定できます。さっそくこの結果を見てみましょう。

緯度と経度で指定した地図上の位置に、とりあえず虫ピンのような最も基本的なアノテーション、MKPointAnnotationを配置してみました

 地図の中心の位置とは微妙にずらしていますが、もちろんまったく同じにしてもかまいません。ただし、あまり離すとピンが地図の表示エリアの外に出てしまい、どこに打ったのか見えなくなってしまうので注意しましょう。

 虫ピンだけでも寂しいので、これに簡単なラベル(コールアウト)を付けてみましょう。タイトルとサブタイトルという2行の文字列からなるラベルなら、それぞれの文字列を指定するだけで簡単に表示できます。アノテーションオブジェクトのtitle、subtitleというプロパティに文字列を代入するだけです。

ano.title = "ASCII倶楽部"
ano.subtitle = "Swiftプログラミング"

 ラベルはピンを刺しただけでは表示されません。表示されたピンにユーザーがタッチすることで表示されるようになります。

アノテーションオブジェクトのtitleとsubtitleの各プロパティに文字列を指定することで、コールアウトと呼ばれるラベルを表示できます

ビューコントローラーを用意して、アノテーションのビューをカスタマイズ

 せっかくのアノテーションが文字列だけでは寂しいと誰もが感じるでしょう。アノテーションには画像やボタンを配置することができます。まずは画像を配置してみましょう。そのための画像は、iCloudドライブにアップしておき、プレイグラウンドの右上の「+」ボタンをタップして、リソースファイルとして読み込みます。ここではASCII倶楽部のページから拾ったロゴをPNG画像として保存しました。

 アノテーションをカスタマイズするには、アノテーション用のビューを用意しなければなりません。また、そのビューは、マップビューからの要求に応じて、随時提供できるようにしておく必要があります。これはテーブルビューからの要求に応じて、随時セルの内容を返せるようにしていたのに似ています。実際、アノテーションとセルの共通点は多いのです。

 マップビューからの要求に応じて何かのコードを実行するには、そのコードを何らかのオブジェクトの中で定義し、そのオブジェクトをマップビューのデリゲート(delegate=代理人)として設定しておく必要があります。そこで、新たに独自のビューコントローラーを用意して、そのビューコントローラーをMKMapViewDelegateに指定します。また、そのビューコントローラーのコードでは、viewDidLoadメソッドの中で、これまでに見てきたマップビューの作成と設定、アノテーションの作成と設定を実行するようにします。

 位置関係を明確にするために、その部分のコードを画面ショットとして示します。

マップビューを管理するビューコントローラーを用意し、そのviewDidLoadメソッドの中で、地図の基本的な設定とアノテーションの作成を実行するためのコードです

 またビューコントローラーの中には、アノテーションを作って返すためのメソッドも記述します。その中では、アノテーションビューのコールアウトの左側に配置する画像をイメージビューとして設定します。その部分のコードは、実行結果と一緒に画面で確認してください。

ビューコントローラーの中には、viewDidLoadに続けて、もう1つのメソッドを記述します。これは、必要に応じてマップビューから呼び出され、画像付きのコールアウトのビューを作成して返すものです

 これで、なんとか見た目も整ったコールアウトを表示できるようになりました。

ボタンを追加して「マップ」と連動させる

 コールアウトの右側にも別のビューをはめ込むことができます。そこにはボタンを配置して、何らかのアクションを実行できるようにするのが普通です。ここでは、そのボタンから「マップ」アプリを起動して画面を切り替え、現在位置からアノテーションを立てた位置までの経路を表示するようにしてみましょう。そのような複雑な機能もMapKitを使ってかなり簡単に実現できます。

 コールアウトの右側にボタンを配置するコードは、上の例で画像を配置するために用意したメソッドの中に続けて記述します。

anoView?.rightCalloutAccessoryView = UIButton(type: .infoLight) as! UIView

 ここではシステムが用意している情報を表示するためのボタン(マルの中にiの文字)を利用しています。

 また、そのボタンがタップされた際に呼び出されるメソッドは、同じビューコントローラーの中に、さらにもう1つのメソッドとして記述します。それらのコードは画面で確認しましょう。

上のビューコントローラーの中のメソッドに、右側のボタンを追加するコードを追加し、もう1つのメソッド(calloutAccessoryControlTapped)を記述します

 このコードを実行して、表示されたピンの頭にタッチすると、右側にボタンが追加されたコールアウトが現れます。

情報ボタンを埋め込むコードを追加した後でアノテーションを表示し、ピンをタップすると、当然ながらコールアウトの右側には、そのボタンも表示されます。これをタップしてみましょう

 そのボタンをタップすると「マップ」アプリが起動して画面がそちらに切り替わります。経路を検索するのにしばらく時間がかかりますが、現在位置からピンを立てた位置までの経路が表示されます。あとは「マップ」アプリの操作で、いろいろな情報を得ることができるでしょう。

コールアウト上の情報ボタンをタップすると、「マップ」アプリが自動的に起動して、画面がそちらに切り替わり、ユーザーの現在位置からアノテーションを設定した位置までの経路が表示されます

次回の予定

 今回は、MapKitを使って地図の上にアノテーションを表示し、さらに「マップ」アプリと連携させてみました。次回もMapKitを扱います。いわゆる「逆ジオコーディング」というテクニックを使って、地図の上をタップするとその場所の住所を表示する機能に挑戦します。

■今回作ったプログラム

Swift_39-1
Swift_39-1
Swift_39-3

mobileASCII.jp TOPページへ

mobile ASCII

Access Rankingアクセスランキング