koogawa blog

iOS、Android、foursquareに関する話題

Swift と MapKit で地図アプリを作成する(後編)

こちらの後編です。

blog.koogawa.com

前回は地図を画面いっぱいに表示するところまで実装しました。今回は地図上にピンを表示していきます。

ピンを表示する

地図上にピンを表示するためには MKPointAnnotation オブジェクトを使用します。このオブジェクトの coordinate プロパティにピンを表示する緯度経度を指定して、MapView に addAnnotation メソッドで追加します。

let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(37.331652997806785, -122.03072304117417)
self.mapView.addAnnotation(annotation)

ピンが表示できました!

kobito.1446341336.196316.png

ピンのタイトルを指定する

これだけだとピンをタップしても何も起こりません。MKPointAnnotation クラスはプロパティに titlesubtitle を持っており、これに文字列を指定することで、ピンをタップした時にタイトルを表示するバルーンを出すことができます。

let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(37.331652997806785, -122.03072304117417)
annotation.title = "title"
annotation.subtitle = "subtitle"
self.mapView.addAnnotation(annotation)

ピンをタップすると、バルーンが表示されると思います。

スクリーンショット 2015-11-01 10.41.58.png

ピンにアニメーションを付ける

ピンが上から降ってくるようにしてみます。

まずは MapView のデリゲートを ViewController.swift にセットします。Story Board で MapView を選択し、画面右側の「Connections Inspector」にある delegate の ○ と、画面左側の View Controller をドラッグアンドドロップで結びつけます。

kobito.1446342647.235789.png

次のようになっていれば delegate がセットできています。

kobito.1446343620.612640.png

次に、MapView のデリゲートメソッドを実装していきます。クラス宣言部に MKMapViewDelegate を追記します。

class ViewController: UIViewController, MKMapViewDelegate {

続いて viewForAnnotation デリゲートメソッドを実装します。このメソッドはピンが画面に表示する直前に呼ばれ、今から表示するピンの属性や外観などを MKPinAnnotationView オブジェクトを使って指定することができます。

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation {
        return nil
    }

    let reuseId = "pin"
    var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
    if pinView == nil {
        pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
        pinView?.animatesDrop = true
    }
    else {
        pinView?.annotation = annotation
    }
        
    return pinView
}

ピンは何度も再利用されます(UITableViewCell のようなイメージ)。最初に dequeueReusableAnnotationViewWithIdentifier で再利用できるピンを取り出します。再利用できるものがなければ新たに作成します。

アニメーションを付けるには animatesDrop プロパティに true を指定します。これでピンが上から降ってくるようになります。

demo.gif

ピンの色を変更する

ピンの色はデフォルトで赤ですが、MKPinAnnotationViewpinTintColor プロパティをセットすることで好きな色に変更できます。

pinView?.pinTintColor = UIColor.purpleColor()

kobito.1446344860.152417.png

バルーンにボタンを付けてみる

バルーンに UIButton を付けることもできます。まずは MKPinAnnotationViewcanShowCallout プロパティを true にセットします。これをやらないとバルーンが表示されないので注意してください。

pinView?.canShowCallout = true

次に、UIButton を生成して rightCalloutAccessoryView プロパティにセットします。

let rightButton: AnyObject! = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView

これでバルーンにボタンが表示されました。

kobito.1446344956.686867.png

ボタンがタップされると calloutAccessoryControlTapped デリゲートが呼ばれます。ここに必要な処理を書いていくと良いでしょう。

func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
    print(__FUNCTION__)
}

まとめ

今回は地図上にピンを表示するところまで実装しました。うまく動かない場合は、デリゲートがちゃんと指定されているか?デリゲートメソッドが呼ばれているか?を確認してみてください。

この記事内では割愛しましたが、地図上にはピンだけでなく 画像 を表示することもできます。また、ピンをドラッグして移動することもできます。興味のある方は私のサンプルコードを参照してください。

この記事が皆さまのお役に立てれば幸いです。