Takahiro Octopress Blog

-1から始める情弱プログラミング

Google Maps SDK for iOSを導入してみよう!

はじめに

本日はGoogle Maps SDK for iOSの導入の仕方を書きたいと思います。
(3年以上前に遊んでいたようですが、全く記憶にない…)

基本的には、本家のスタートガイドに従って進めるだけで特に問題なくGoogle Mapを実装できるでしょう。
筆者の場合はStoryboardを使いたかったので少し気をつける必要がありました。
では早速見ていきましょう。

Google Maps SDK for iOSの導入

実際に手順を書いていきます。

1.Xcodeでプロジェクトを作成します。
2.Podfileを作成します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Podfile
use_frameworks!

target "GoogleMapsSample" do
  # Normal libraries
  pod 'GoogleMaps'
  pod 'GooglePlaces'

  abstract_target 'Tests' do
    inherit! :search_paths
    target "GoogleMapsSampleTests"
    target "GoogleMapsSampleUITests"

    pod 'Quick'
    pod 'Nimble'
  end
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['SWIFT_VERSION'] = '3.0'
    end
  end
end

3.pod installで必要なFrameworkをインストールします。
4.APIキーを取得します。
スタートガイドに従って下記ボタンをクリックすればAPIキーを取得することができます。

APIキーの取得

5.アプリのAPIキーを読み取らせる処理を導入します。
筆者の場合、基本的なソースコードはGitHubに公開したかったため、そのままAPIキーをべた書きするわけにいきませんでした。
なので、key.plistファイルを作成し、このファイルをGitHubにアップしないという手法を取ることにしました。

下図のようにkey.plistファイルを作成

key.plistの作成

また下図のようなフォルダ構成でInfo.plistと同じ階層にkey.plistを配置しています。
フォルダ構成

AppDelegate.swiftkey.plistからAPIキーを読み込みます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// AppDelegate.swift
import UIKit
import GoogleMaps
import GooglePlaces

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    if let path = Bundle.main.path(forResource: "key", ofType: "plist") {
      if let dic = NSDictionary(contentsOfFile: path) as? [String: Any] {
        if let apiKey = dic["googleMapsApiKey"] as? String {
          GMSServices.provideAPIKey(apiKey)
          GMSPlacesClient.provideAPIKey(apiKey)
        }
      }
    }

    return true
  }
    ...
}

6.StoryboardGoogle Mapを追加します。
本家スタートガイドだとStoryboardを利用しない方式での説明が書かれていましたが、筆者はStoryboardを利用しました。

StoryboardにGoogle Mapを配置

これで導入が完了です。

Google Cloud PlatformのAPI Managerで詳細設定

先程、本家のスタートガイドからAPIキーを取得していましたが、Google Cloud Platform内のAPI ManagerからAPIキーに対して詳細設定をすることができます。
例えば、スタートガイドから取得しただけでは、APIキーの用途が無制限になっています。
この状態では意図しない大量利用に繋がる可能性もあるため、iOSアプリでのみ利用するなど詳細を設定した方が良いでしょう。

API Managerページには下記のように遷移できます。
Google Cloud Platform

APIキーの詳細設定は下記の通りです。
APIキーの詳細設定

Google Mapで初期描画時の中心位置を現在地にしてみる

Apple標準で用意されているMapKitであれば、

1
self.mapView.setUserTrackingMode(MKUserTrackingMode.follow, animated: true)

とすれば良いだけでした。
しかし、Google Mapでは同様の手立てがなさそうなので、下記のように対応しました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// ViewController.swift
import UIKit
import GoogleMaps
import GooglePlaces

class ViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate {

  @IBOutlet weak var mapView: GMSMapView!
  private var locationManager: CLLocationManager?
  private var currentLocation: CLLocation?
  private var placesClient: GMSPlacesClient!
  private var zoomLevel: Float = 15.0
  /// 初期描画の判断に利用
  private var initView: Bool = false

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    // GoogleMapの初期化
    self.mapView.isMyLocationEnabled = true
    self.mapView.mapType = GMSMapViewType.normal
    self.mapView.settings.compassButton = true
    self.mapView.settings.myLocationButton = true
    self.mapView.delegate = self

    // 位置情報関連の初期化
    self.locationManager = CLLocationManager()
    self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
    self.locationManager?.requestAlwaysAuthorization()
    self.locationManager?.distanceFilter = 50
    self.locationManager?.startUpdatingLocation()
    self.locationManager?.delegate = self

    self.placesClient = GMSPlacesClient.shared()
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  // MARK: CLLocationManagerDelegate
  func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if !self.initView {
      // 初期描画時のマップ中心位置の移動
      let camera = GMSCameraPosition.camera(withTarget: (locations.last?.coordinate)!, zoom: self.zoomLevel)
      self.mapView.camera = camera
      self.locationManager?.stopUpdatingLocation()
      self.initView = true
    }
  }
}

これはviewDidLoad時にstartUpdatingLocation()で位置情報の取得を開始し、取得したタイミングであるdidUpdateLocations内で位置情報をcameraに設定しています。
(もっと良い方法がありそうな気もしますが、一旦これで様子見…)

まとめ

さて如何でしたでしょうか?
これからGoogle Maps SDK for iOSをバシバシ使っていきたいと思っているので理解が進み次第、続きを書いていきたいと思います。
と言ったところで本日はここまで。

Comments