携帯端末の強みの一つとして、GPS 機能があります。その位置情報の活用方法としては様々なものがありますが、代表的なものは地図表示ではないでしょうか。iOS の MapKit にはデフォルトで位置を表示するピンが用意されていますが、最近自作のピンを設定する機会があったので、その方法について書きたいと思います。
MapKit のざっくりとした使い方
MapKit を使うにあたってのざっくりとした流れは
- MapKit.framework を追加
- MapKit/MapKit.h を import
- MKMapView を作成し、MKMapViewDelegate で制御
となります。
MKMapView およびそのサブクラスという意味で、以下マップビューと呼ぶことにします。同様に、MKAnnotationView およびそのサブクラスという意味でアノテーションビューと呼ぶことにします。
マップビューを使ったとき、アノテーションビューの描画は MKMapViewDelegate の
mapView:viewForAnnotation:
で行われます。
テーブルビューを使ったとき UITableViewDelegate の
tableView:cellForRowAtIndexPath:
で処理するのに似ています。
mapView:viewForAnnotation: での処理
よくある現在地を青丸で表示するのは、
if ([annotation isKindOfClass:[MKUserLocation class]]) { return nil; }
とやるだけでできます。ただし、マップビューの showsUserLocation プロパティを YES にしておく必要があります。
現在地以外のアノテーションビューを設定する場合は、例としてクラスを MyAnnotationView とすると
static NSString* MyAnnotationIdentifier = @"MyAnnotationIdentifier"; MKPinAnnotationView* pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:MyAnnotationIdentifier]; if (!pinView) { MyAnnotationView *annotationView = [[[MyAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MyAnnotationIdentifier] autorelease]; return annotationView; }
などとやればできます。テーブルビューでセルを再利用するように、マップビューでもアノテーションビューを再利用していますので書き方も似ていますね。
問題は、このアノテーションビューがどこに描画されるかということですが、アノテーションビューのちょうど中心が地図の座標にマッピングされます。そのため、自作のピン画像を設定する場合はピンの先が画像の中心にくるように作らなければなりません。
しかし、場合によっては画像だけでは対応できない場合もあります。そんなときはアノテーションビューの centerOffset プロパティで調整します。centerOffset プロパティはアノテーションビューのどこをマップ上での座標にマッピングするかを設定できます。
例えば、画像の右下を地図の座標に合わせたいという場合、画像のサイズが (20, 20) だとすると、デフォルトの状態だと (10, 10) の位置が座標にマッピングされますので、
annotationView.centerOffset = CGPointMake(-10, -10);
などとやります。
補足:タッチイベントのハンドリング
通常、アノテーションビューのタッチイベントは、MKMapViewDelegate の
mapView:didSelectAnnotationView:
で行いますが、それよりもアノテーションビューの
touchesBegan:withEvent:
の方がイベントを先に受け取りますので、マップビューでのタッチイベントのハンドリングで困ったときはアノテーションビューの方でハンドリングすると解決することもあるかもしれません。