Places SDK for iOS(Objective-C)を使ってみる

1. 始める前に

コーディングを開始する前に、いくつかの前提条件を設定する必要があります。

Xcode

このチュートリアルでは、Apple の Xcode ツールと Objective-C 言語を使用して、エミュレータで実行されるシンプルな iOS アプリケーションを作成します。実機は必要ありません。Xcode は https://developer.apple.com/xcode/ から入手できます。

CocoaPods

Places SDK for iOS は CocoaPods pod として提供されています。CocoaPods は、Swift プロジェクトと Objective-C プロジェクト用のオープンソースの依存関係管理ツールです。このツールをまだお持ちでない場合は、先に進む前にインストールする必要があります。ターミナルから次のようにインストールできます。

sudo gem install cocoapods

CocoaPods の詳細については、CocoaPods スタートガイドをご覧ください。

SDK のインストール

SDK をインストールするには、CocoaPods が必要な依存関係をダウンロードして構成するために使用する Podfile をプロジェクト ディレクトリに作成する必要があります。最も簡単な方法は、Xcode で新しいプロジェクトを作成し、そこに Podfile を追加して、Pod をインストールすることです。

Xcode を開くと、[Welcome to Xcode] 画面が表示されます。[Create a new Xcode project] を選択します。

4f1ecee473937c7b.png

次の画面で、新しいプロジェクトのテンプレートを指定するよう求められます。iOS で [Single View Application] を選択し、[Next] を押します。

プロダクト名を入力するよう求められたら、任意の名前を入力できますが、生成されたバンドル ID を必ずメモしておいてください。これは後で必要になります。

72fbf25cb2db22ad.png

[次へ] を押すと、プロジェクトが作成されます。作成されたディレクトリをメモしておきます。Xcode を閉じ、ターミナルを使用してそのディレクトリに移動します。

ターミナルを使用して、次のコマンドを入力します。

pod init

Podfile というファイルが作成されます。次のように編集して、GoogleMaps の Pod を追加します。

target '{YOUR APP NAME}' do
pod 'GoogleMaps'
end

保存して Xcode を閉じます。次のステップで基盤となるプロジェクトを編集するため、必ず閉じてください。完了したら別のプロジェクト ファイルを開くことになります。Xcode を閉じていないと、すべてがどこにあるのか混乱することがよくあります。ターミナルでプロジェクト ディレクトリに移動し、次のように「pod install」を実行します。

789c5bc62817f68a.png

完了すると、Pod がインストールされ、新しい .xcworkspace ファイルが作成されます。今後はこのプロジェクトを使用してください。コーディングの前に、API キーが必要です。

2. API キーを取得する

以下の有効化の手順では、Maps SDK for iOS を有効化します。

Google Maps Platform をセットアップする

課金を有効にした Google Cloud Platform アカウントとプロジェクトをまだ作成していない場合は、Google Maps Platform スタートガイドに沿って請求先アカウントとプロジェクトを作成してください。

  1. Cloud Console で、プロジェクトのプルダウン メニューをクリックし、この Codelab に使用するプロジェクトを選択します。

  1. Google Cloud Marketplace で、この Codelab に必要な Google Maps Platform API と SDK を有効にします。詳しい手順については、こちらの動画またはドキュメントをご覧ください。
  2. Cloud Console の [認証情報] ページで API キーを生成します。詳しい手順については、こちらの動画またはドキュメントをご覧ください。Google Maps Platform へのすべてのリクエストで API キーが必要になります。

3. Places API アプリを作成する

コンソール プロジェクトを作成し、そのプロジェクトで Places API を有効にして API キーを取得したので、最初の Places API アプリのコーディングを開始する準備が整いました。

以前に Pod ファイルをインストールしたときに、新しい .xcworkspace ファイルが作成されました。これをダブルクリックして開きます。

19d62f34c08e645c.png

プロジェクト エクスプローラに「Pods」という新しいフォルダが追加されていることがわかります。成功すると、GoogleMaps フォルダにフレームワークが含まれます。

8844d861f64c61aa.png

4. Info.plist ファイルを編集します。

アプリケーションを初めて実行すると、iOS によって、位置情報サービスへのアクセス権を付与するようユーザーに求めるダイアログが表示されます。このダイアログで定義した文字列が返されるので、それを Info.plist ファイルに配置します。この文字列がない場合、ダイアログは表示されず、アプリは動作しません。

Info.plist ファイルは、プロジェクト エクスプローラで次の場所にあります。

c224c920ab3f1ef.png

選択すると、plist エディタが表示されます。

859ca56f3b19da5.png

いずれかの要素にカーソルを合わせると、プラス記号のアイコンが表示されます。押すと、新しいエントリが表示されます。このボックスに「NSLocationAlwaysUsageDescription」と入力します。

9fb225d6f5508794.png

Enter キーを押して新しいキーを追加します。次に、このキーの [値] 列をダブルクリックして、文字列を追加します。

5aefeb184187aa58.png

この文字列について詳しくは、Apple デベロッパー ドキュメントのこちらをご覧ください。

5. アプリのデリゲートを編集する

プロジェクト エクスプローラで AppDelegate.m を見つけて開きます。これを使用して API キーを追加します。

ファイルの先頭で、#import 行のすぐ下に次の行を追加します。

@import GoogleMaps;

次に、didFinishLaunchingWithOptions: 関数で、「return YES」行の直前に以下を追加します。

[GMSServices provideAPIKey:@"<Add your API Key>"];

必ず、前に生成した API キーを使用してください。

6. ストーリーボード ファイルを編集する

プロジェクト エクスプローラで、Main.storyboard ファイルを開きます。右上にあるサイドバー ボタンを押して、サイドバーがアクティブになっていることを確認します。

352af28b970d9e2.png

次に、サイドバーの下部で、オブジェクト ライブラリが選択されていることを確認して、ラベル コントロールを見つけます。

adec7051ae949531.png

左側の View Controller Scene で、[View] が選択されていることを確認します。

e4827b92b5861e3e.png

次に、7 つのラベルをビューにドラッグ&ドロップします。図のように配置します。表示されているサイズに合わせてサイズをドラッグしてください。ラベルのテキストを編集するには、ラベルをダブルクリックして必要な値を入力します。

f8a9457772358069.png

一番下のラベル(非常に大きいラベル)については、プロパティ エディタで、行数が 0 に設定されていることを確認します(デフォルトは 1 です)。これにより、複数行をレンダリングできるようになります。

a4abacf00d8888fe.png

7. 値のアウトレットを作成する

3 つの「value」ラベルについては、アウトレットを作成する必要があります。これにより、コードを使用して値を変更できるようになります。これを行うには、まずアシスタント エディタを有効にする必要があります。そのためには、まずプロパティ サイドバーのボタンをクリックして、サイドバーを閉じます。(このボタンは前のステップで表示されました)

次に、アシスタント ボタン(下の図の二重丸のボタン)を選択します。

e92dcc4ceea20a51.png

ViewController.h ファイルがレンダリングされていることを確認します。そうでない場合は、アシスタント ウィンドウの上部にあるエディタを使用して、次のように変更できます。

d42f0fcc18b84703.png

次に、CONTROL キーを押しながら各ラベルをドラッグして、アシスタントの ViewController.h ファイルの @interface 行の下にドロップします。接続の種類を選択するダイアログが表示されます。

a44b7888ed0f62b.png

設定が図のとおり([Connection]: [Outlet]、[Type]: [UILabel]、[Storage]: [Weak])になっていることを確認し、それぞれに名前を付けます。この Codelab では、Longitude、Latitude、Altitude のラベルをそれぞれ lblLongitude、lblLatitude、lblAltidude と呼びます。また、下部から大きなラベルをドラッグして、lblPlaces と呼びます。

完了すると、ViewController.h ファイルは次のようになります。

#import <UIKit/UIKit.h>
@import GoogleMaps;

@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *lblLatitude;
@property (weak, nonatomic) IBOutlet UILabel *lblLongitude;
@property (weak, nonatomic) IBOutlet UILabel *lblAltitude;
@property (weak, nonatomic) IBOutlet UILabel *lblPlaces;

@end

8. Location API と Google Client API のヘッダー ファイルを編集する

最終手順(Places API を使用するアプリのビルド)の前に、ヘッダー ファイル(ViewController.h)でいくつかの変数を設定する必要があります。Core Location Manager と Core Location オブジェクトは次のとおりです。

@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLLocation *location;

Google API クライアントも必要です。

@property GMSPlacesClient *placesClient;

最後に、クラスが CLLocationManagerDelegate を実装するようにヘッダー ファイルを更新する必要があります。

@interface ViewController : UIViewController<CLLocationManagerDelegate>

完了すると、ヘッダー ファイルは次のようになります。

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <GoogleMaps/GoogleMaps.h>


@interface ViewController : UIViewController<CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLLocation *location;
@property (weak, nonatomic) IBOutlet UILabel *lblLongitude;
@property (weak, nonatomic) IBOutlet UILabel *lblLatitude;
@property (weak, nonatomic) IBOutlet UILabel *lblAltitude;
@property (weak, nonatomic) IBOutlet UILabel *lblPlaces;

@property GMSPlacesClient *placesClient;
@end

9. ビュー コントローラを編集する

まず、viewDidLoad 関数を編集して、Location Manager を初期化し、位置情報へのアクセスに関するユーザーの承認をリクエストします。最後に、現在地を追跡するように Location Manager を起動します。また、Google Places API クライアントも初期化します。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc]init];
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.locationManager requestAlwaysAuthorization];
        // Or [self.locationManager requestWhenInUseAuthorization];
    }
    [self.locationManager startUpdatingLocation];
    
    self.locationManager.delegate = self;
    self.location = [[CLLocation alloc] init];
    self.placesClient = [GMSPlacesClient sharedClient];
}

10. 位置情報の更新を処理する

ロケーション マネージャーは、didUpdateLocations 関数を呼び出して、位置情報の更新を View Controller にコールバックします。これを ViewController.m に追加する必要があります。関数は次のようになります。

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    // Enter code here
}

この関数はいくつかの処理を行う必要があります。

まず、最後に受信した位置情報で位置情報をキャッシュに保存します。

self.location = locations.lastObject;

次に、緯度、経度、高度の 3 つのラベルを更新します。

self.lblLatitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.latitude];

self.lblLongitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.longitude];

self.lblAltitude.text = [NSString stringWithFormat:@"%f", self.location.altitude];

次に、places クライアントを使用して Places API を呼び出します。これを行うには、場所の可能性のリストを取得するコールバック関数を指定します。Places API は、位置情報に基づいて特定の場所にいる可能性を判断します。その場所にいる確率を含む 0 ~ 1 の値とともに、可能性の高い場所の名前を返します。

[self.placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *likelihoodList, NSError *error) {

その後、コールバックを実装できます。これにより、可能性のリストが反復処理され、場所と、その場所の可能性が追加されます。

[self.placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *likelihoodList, NSError *error) {

  if (error != nil) {
    NSLog(@"Current Place error %@", [error localizedDescription]);
    return;
  }
  NSMutableString *strPlaces = [NSMutableString stringWithString:@""];

  for (GMSPlaceLikelihood *likelihood in likelihoodList.likelihoods) {
    GMSPlace* place = likelihood.place;
    NSLog(@"Current Place name %@ at likelihood %g", place.name,
            likelihood.likelihood);
    NSLog(@"Current Place address %@", place.formattedAddress);
    NSLog(@"Current Place attributions %@", place.attributions);
    NSLog(@"Current PlaceID %@", place.placeID);
    [strPlaces appendString:place.name];
    [strPlaces appendString:@" "];
    [strPlaces appendFormat:@"%g",likelihood.likelihood];
    [strPlaces appendString:@"\n"];
  }
  self.lblPlaces.text = strPlaces;
}];

完了すると、didUpdateLocations 関数は次のようになります。

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    
    self.location = locations.lastObject;
    self.lblLatitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.latitude];
    self.lblLongitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.longitude];
    self.lblAltitude.text = [NSString stringWithFormat:@"%f", self.location.altitude];
    
    NSLog(@"%@", self.location.description);
    
    [self.placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *likelihoodList, NSError *error) {

        if (error != nil) {
            NSLog(@"Current Place error %@", [error localizedDescription]);
            return;
        }
        NSMutableString *strPlaces = [NSMutableString stringWithString:@""];
        
        for (GMSPlaceLikelihood *likelihood in likelihoodList.likelihoods)  
        {
            GMSPlace* place = likelihood.place;
            NSLog(@"Current Place name %@ at likelihood %g", place.name, likelihood.likelihood);
            NSLog(@"Current Place address %@", place.formattedAddress);
            NSLog(@"Current Place attributions %@", place.attributions);
            NSLog(@"Current PlaceID %@", place.placeID);
            [strPlaces appendString:place.name];
            [strPlaces appendString:@" "];
            [strPlaces appendFormat:@"%g",likelihood.likelihood];
            [strPlaces appendString:@"\n"];
        }
        self.lblPlaces.text = strPlaces;
    }];
}

これで、アプリを実行してテストする準備が整いました。

11. エミュレータでアプリを実行する

アプリは、タイトルバーの実行ボタンを使用して実行します。実行タイプを選択することもできます。ご覧のとおり、エミュレータを使用して iPhone 6 でテストしています。

bbbe0b8820c8a913.png

実行ボタンを押すと、アプリがビルドされて起動します。アプリが位置情報にアクセスすることを許可するリクエストが表示されます。これには、先ほど指定したカスタム文字列が含まれています。

b9bb2ace7e68f186.png

この操作を行うと、緯度と経度が更新されます。場所を変更するには、[デバッグ] メニューを選択して場所を選択します。たとえば、[Freeway Drive] を選択できます。

dcb1ce091d780f56.png

この操作を行うと、高速道路の走行をシミュレートして、場所と候補地が更新されます。

649e3eeb2321ae03.png

これで完了です。iOS で Google Places API を使用して、現在地の詳細にアクセスできました。