[iOS] Google Maps SDK for iOS を使ってみる – GMSMapViewとGMSMarkerの基本

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

今まで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が必要ですのでお忘れなく!)

  1. Google Maps SDK for iOSの入手
  2. Google Maps API Keyの取得
  3. GoogleMaps.framework等のフレームワークをプロジェクトに追加
  4. 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) デフォルトのマーカー

ios-map-programming-series-1-00

    // (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) マーカーのアイコンをカスタム画像にする場合

ios-map-programming-series-1-01

    // (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) マーカーをタップした時に表示されるウィンドウ自体をカスタムビューにする場合

ios-map-programming-series-1-02

    // (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) マーカーをタップした時に表示されるウィンドウの中のビューをカスタムビューにする場合

ios-map-programming-series-1-03

    // (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のほうがシンプルな手順でマーカーを追加できると感じました。

今回作成したサンプルプロジェクトはこちらで公開していますので参考にしてみてください。

参考資料