iPhone Mapを扱ってみよう

今日はiPhoneアプリケーションでマップを利用する方法を学んだので、ブログに残したいと思います。マップは最初から登録されているマップアプリを代表に各種アプリで使われており、またWeb上でも利用されていて、ユーザーにとって馴染みの深いインターフェースですね。だからより使いやすいインターフェースが求められるかも。今日は簡単なところから。
今回作成した画面はこんな感じです。マップを表示後に、ユーザーの位置を特定し、その位置を中心に表示するという画面です。


マップアプリを作成するためには

マップを画面に表示するのはとても簡単。Interface BuilderでMapViewを追加すれば、画面にマップが表示されます。でもアプリケーションならばマップの操作が通常必要になるかと思います。今回は、マップの表示位置変更、ズーム、ユーザー位置表示を実装してみました。


準備事項

マップアプリを利用するためには、以下の作業が必要です。ヘッダファイルの例を示します。
1、Mapkit.frameworkをアプリケーションに追加する。
2、MKMapViewを利用するヘッダファイルに、Mapkit.frameworkのインポートを宣言する。
3、ヘッダファイルにMKMapViewの宣言を行い、その変数とInterface Builderで追加したMapViewを関連づける。
4、MapViewの動作に合わせて処理を行うため、MKMapViewDelegateプロトコルの実装を宣言する。

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface BasicMapViewController : UIViewController
<MKMapViewDelegate> {
  MKMapView *myMapView;
}
@property(nonatomic, retain) IBOutlet MKMapView *myMapView;
- (IBAction) changeMapType : (id)sender;
- (IBAction) showHere : (id)sender;
@end

changemapType:メソッドは、地図の表示タイプを変更するメソッドです。showHere:は、ユーザーの現在位置を表示するメソッドです。それぞれの詳細はこの後、記載します。


マップを表示する

Interface BuilderでMapViewを作成している場合には、アプリケーションを起動すればマップが表示されます。初期状態のマップは下の図のように表示されるかと思います。ビューが表示されたときにデリゲートを設定したいので、viewDidLoadedメソッドにデリゲートの設定を記載します。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.myMapView.delegate = self;
}


マップの種類を変更する

マップの種類は3種類存在します。通常モード、サテライトモード、ハイブリッドモード。それぞれ切り替えるために、changeMapType:メソッドを以下のように実装しました。切り替えた際のイメージも載せたいと思います。

- (IBAction) changeMapType : (id)sender {
static int mapTypeCount = 0;
switch (mapTypeCount % 3) {
  case0:
  myMapView.mapType = MKMapTypeSatellite;
  break;
  case1:
  myMapView.mapType = MKMapTypeHybrid;
  break;
  case2:
  myMapView.mapType = MKMapTypeStandard;
  break;
}
mapTypeCount++;
}

左から、通常モード、サテライトモード、ハイブリッドモード。


ユーザーの現在位置を表示する&地図のズーム

ユーザーの現在位置表示も簡単に実現できる仕組みが用意されています。showsUserLocationプロパティにYESを設定するのみ。そーすれば、MapViewが自動的にLocationFrameworkを利用して現在位置を特定してくれます。showHere:メソッドで実現します。

- (IBAction) showHere : (id)sender {
// show current location
myMapView.showsUserLocation = YES;
}

ユーザー位置を示しても地図の表示位置が適切でないと、ユーザー位置が見えない可能性があります。そのため、ユーザー位置が特定できた時に、地図の表示位置やズーム度を適切に変更するように実装します。ユーザー位置が特定された場合にはMKMapViewDelegateプロトコルのmapView:didUpdateUserLocation:メソッドが呼び出されます。そのメソッドの実装例を示します。

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
// set center.
[mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];

// zoom in.
MKCoordinateRegion theRegion = mapView.region;
theRegion.span.longitudeDelta /= 40;
theRegion.span.latitudeDelta /= 40;
[mapView setRegion:theRegion animated:YES];
}

ここでは、ユーザー位置を地図の真ん中に設定し、初期表示から40倍にズームしています。表示例は以下です。

その他マップで設定できること

上記では、地図タイプ、地図位置、ズームなどを設定しましたが、MKMapViewでは他にも以下のような設定が行えます。詳細は、MKMapView Class Referenceも参照ください。
■ zoomEnabled:ユーザーによるズームを許可するか否か。
■ scrollEnabled : ユーザーによるスクロールを許可するか否か。
■ region : マップの中心地点と表示範囲をまとめて指定できる。


MKMapViewDelegateにて処理できるイベント

MKMapViewDelegateプロトコルでは、Mapに関する様々なイベント発生時に処理を追加出来ます。上記ではユーザー位置を特定した際の処理を追加しましたが、他にも以下のようなイベントにも対応できます。詳細はMKMapViewDelegate Protocol Referenceも参考にしてみて下さい。
■ マップの表示位置が変更される前/後
■ マップデータがロードされる前/後/エラー時


最後に

今日はMap表示に関する基本的な事を記載しました。でもMapは表示するだけでなく、情報を載せることで価値が上がると思います。次はアノテーションを利用してMap上に情報を表示する方法も記載できればと思います。Mapアプリは作成できると楽しそうだなぁ。でも画像描画やカスタム情報表示方法をする場合には、CoreGraphicsFrameworkも必要そうで、奥が深そうだなと感じました。
最後に私のTwitter@yoheiMune)も宜しくお願いします。