[iOS] Google Maps SDK for iOS を使ってみる – GMSMapViewとGMSMarkerの基本
はじめに
今までiOS標準のMap Kit Frameworkを使って地図機能を実装することはありましたが、Google Maps SDK for iOSを使ったことはありませんでした。最近初めて使ってみましたので、Map KitとGoogle Maps SDKの違いを確認しつつ基本的な項目をまとめてみます。
本記事執筆時のGoogle Maps SDK for iOSの最新版は1.8.1になっています。 SDK1.8.1がサポートするXcode/iOS SDKのバージョンは以下の通りです。
バージョン | |
Xcode | 5.0以上 |
iOS SDK | 7.0以上 |
SDKの準備
地図を表示するまでの手順は以下のようになります。こちらの公式ドキュメントを参考に準備してみてください。(地図を使うにはAPI Keyが必要ですのでお忘れなく!)
- Google Maps SDK for iOSの入手
- Google Maps API Keyの取得
- GoogleMaps.framework等のフレームワークをプロジェクトに追加
- GMSMapViewクラスを使用して地図を実装
基本的な使い方
APIキーの指定
AppDelegateクラスのapplication:didFinishLaunchingWithOptions:メソッドに、SDKの準備で取得したAPIキーを指定するコードを追加します。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GMSServices provideAPIKey:@"(ここにAPI_KEYを入力)"]; return YES; }
GMSMapViewの作成
MapKitで地図を表すクラスはMKMapViewクラスですが、Google Maps SDK for iOSにおいてMKMapViewに相当するクラスはGMSMapViewクラスになります。GMSMapViewの使用例について見ていきます。
- (void)viewDidLoad { [super viewDidLoad]; // (1) GMSCameraPositionインスタンスの作成 GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:35.698717 longitude:139.772900 zoom:16.0]; // (2) GMSMapViewインスタンスの作成 self.mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera]; // (3) myLocationEnabledプロパティ self.mapView.myLocationEnabled = YES; // (4) settings.myLocationButtonプロパティ self.mapView.settings.myLocationButton = YES; // (5) delegateの設定 self.mapView.delegate = self; self.view = self.mapView; [self addMarkers]; }
(1) GMSCameraPositionインスタンスの作成
Google Maps SDK for iOSでは「カメラ」という概念を使って、マップの中心座標やズームレベルなどを設定します。ここでは中心座標とズームレベルを指定してGMSCameraPositionインスタンスを作成しています。地図の回転や、地平面に対する角度も指定できるコンビニエンスコンストラクタもあるようです。
(2) GMSMapViewインスタンスの作成
(1)で作成したGMSCameraPositionを使ってGMSMapViewインスタンスを作成しています。
(3) myLocationEnabledプロパティ
ユーザーの現在地にドットを表示するにはGMSMapViewのmyLocationEnabledプロパティにYESを指定します。
(4) settings.myLocationButtonプロパティ
GMSMapViewのsettingsプロパティ(GMSUISettings)は地図UIの設定値を保持します。その中の myLocationButtonプロパティにYESを指定すると、画面右下に現在地ボタンが表示されます。
(5) delegateの設定
GMSMapViewDelegateにはマーカーがタップされたり、ポップアップ画面がタップされりした時に呼ばれるメソッドなどが用意されています。
GMSMarkerの作成
MapKitでは特定の場所に描画するアイコンのことを注釈(アノテーション)と呼び、MKAnnotationViewクラスを使います。 Google Maps SDK for iOSにおいては、アイコンのことをマーカーと呼び、MKAnnotationViewに相当するクラスはGMSMarkerになります。
今回のサンプルで使用しているGMSMarkerのプロパティは以下のとおりです。
名前 | 型 | 内容 |
title | NSString | タイトル |
snippet | NSString | サブタイトル |
position | CLLocationCoordinate2D | 座標 |
map | GMSMapView | ここに指定したGMSMapView上にGMSMarkerが表示される (nilを指定すると地図上から削除される) |
userData | id | マーカーに関連したデータを格納 (今回のサンプルではマーカーの識別子を格納) |
icon | UIImage | マーカー用の画像 |
(6) デフォルトのマーカー
// (6) デフォルトのマーカー GMSMarker *yodobashiMarker = [[GMSMarker alloc] init]; yodobashiMarker.title = @"ヨドバシAkiba"; yodobashiMarker.snippet = @"千代田区神田花岡町1−1"; yodobashiMarker.position = CLLocationCoordinate2DMake(35.698852, 139.774761); yodobashiMarker.map = self.mapView; yodobashiMarker.userData = [NSNumber numberWithInteger:markerIdYodobashi];
positionプロパティに座標を、mapプロパティにGMSMapViewを指定すると、指定したGMSMapView上にマーカーが表示されます。マーカーがタップされた時に表示されるウィンドウ上に、titleとsnippetプロパティに指定した文字列が表示されます。titleとsnippetに何も指定しなかった場合はウィンドウ自体が表示されません。
(7) マーカーのアイコンをカスタム画像にする場合
// (7) マーカーのアイコンをカスタム画像にする場合 GMSMarker *akihabaraStationMarker = [[GMSMarker alloc] init]; akihabaraStationMarker.title = @"秋葉原駅"; akihabaraStationMarker.snippet = @"千代田区外神田1丁目"; akihabaraStationMarker.position = CLLocationCoordinate2DMake(35.698404, 139.773001); akihabaraStationMarker.map = self.mapView; akihabaraStationMarker.icon = [UIImage imageNamed:@"pin"]; akihabaraStationMarker.userData = [NSNumber numberWithInteger:markerIdAkihabaraStation];
iconプロパティにUIImageを指定すると、マーカーのアイコンが指定した画像になります。
指定した画像の下端がpositionで指定した座標と重なるように描画されます。
(8) マーカーをタップした時に表示されるウィンドウ自体をカスタムビューにする場合
// (8) マーカーをタップした時に表示されるウィンドウ自体をカスタムビューにする場合 GMSMarker *classmethodMarker = [[GMSMarker alloc] init]; classmethodMarker.title = @"クラスメソッド株式会社"; classmethodMarker.snippet = @"千代田区神田佐久間町1丁目11番地"; classmethodMarker.position = CLLocationCoordinate2DMake(35.697236, 139.774718); classmethodMarker.map = self.mapView; classmethodMarker.userData = [NSNumber numberWithInteger:markerIdClassmethod];
マーカーがタップされたタイミングでmapView:markerInfoWindow:メソッド(GMSMapViewDelegateのメソッド)が呼ばれます。
以下のサンプルのように、このメソッドでViewを返すことで、マーカータップ時に表示されるウィンドウがカスタムビューになります。
(mapView:markerInfoWindow:メソッドでnilを返すとデフォルトのウィンドウが表示されます。)
// ウィンドウを返却する - (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker { NSInteger markerId = [marker.userData integerValue]; if (markerId == markerIdClassmethod) { UIView *view = [[[NSBundle mainBundle] loadNibNamed:@"View" owner:self options:nil] lastObject]; return view; } else { return nil; } }
(9) マーカーをタップした時に表示されるウィンドウの中のビューをカスタムビューにする場合
// (9) マーカーをタップした時に表示されるウィンドウの中のビューをカスタムビューにする場合 GMSMarker *denkigaiMarker = [[GMSMarker alloc] init]; denkigaiMarker.title = @"電気街"; denkigaiMarker.snippet = @"千代田区外神田2丁目2−16−2"; denkigaiMarker.position = CLLocationCoordinate2DMake(35.699649, 139.771419); denkigaiMarker.map = self.mapView; denkigaiMarker.userData = [NSNumber numberWithInteger:markerIdDenkigai];
mapView:markerInfoWindow:メソッドでnilを返却した場合、マーカーがタップされたタイミングでmapView:markerInfoContents:メソッド(GMSMapViewDelegateのメソッド)が呼ばれます。
以下のサンプルのように、このメソッドでViewを返すことで、マーカータップ時に表示されるウィンドウ内のビューがカスタムビューになります。
mapView:markerInfoContents:メソッドでnilを返すとデフォルトのコンテンツ(タイトルとサブタイトル)が表示されます。
// ウィンドウ内のコンテンツビューを返却する - (UIView *)mapView:(GMSMapView *)mapView markerInfoContents:(GMSMarker *)marker { NSInteger markerId = [marker.userData integerValue]; if (markerId == markerIdDenkigai) { UIImage *image = [UIImage imageNamed:@"photo.jpg"]; UIImageView *imageView = [[UIImageView alloc]initWithImage:image]; return imageView; } else { return nil; }
まとめ
今回はGoogle Maps SDK for iOSの基本的な部分を見ていきました。MapKitとGoogle Maps SDK for iOSとではマーカーの実装方法が異なります。Google Maps SDK for iOSのほうがシンプルな手順でマーカーを追加できると感じました。
今回作成したサンプルプロジェクトはこちらで公開していますので参考にしてみてください。