Google Maps SDK for iOS を Titanium Mobile の Alloy で使う

## 僕は Google Maps が使いたい。iOSで。Titaniumで。Alloyで。
突然ですが僕は地図が大好きです。ヒマがあれば Google Maps を眺めて色々妄想しております。最近 Google Maps アプリが iPad にも対応したので、トイレ地図がとても捗り重宝しております。
それに引き換え、「パチンコガンダム駅」などで話題になった iOS 6 以降の Apple Maps。最近かなり改善されているとは思うのですが、Google Maps に比べると、まだまだ劣っていると言わざるをえません。

Titanium Mobile で iOSアプリを開発し、そこに地図を載せたいと思った場合、普通にやってしまうと Apple Maps を利用することになってしまいます。地図スキーな僕として、常々これは何とかしたいと思っておりました。iOSアプリ でも Google Maps が使いたい。使いたいんだ！

幸い Google 様から、iOS用の Google Maps SDK が公開されております。それを Titanium Mobile に組み込み、Alloy から使ってしまおう！というのが、この記事の趣旨になります。

## モジュールを調達する
Titanium Mobile から iOS用の Google Maps SDK を利用する場合、Titanium のお作法に則って モジュール化 することが必要になります。

さてそのモジュールですが、以下の方法で入手できます。

+ 自分で作る
+ [github](http://github.com)などで公開されているのを探す
+ [Appcelerator Marketplace](http://marketplace.appcelerator.com/) で購入する

わたくし[@sngmr](http://twitter.com/sngmr)こと森 真吾は、面倒くさいことが大キライです。すぐに Google Maps を Titanium Mobile から使いたいんです。というわけで、Appcelerator Marketplace から購入することにしました。そのものズバリなモジュールが売っていたので。開発者あたり$30です。

> **Google Maps for iOS**:
> [https://marketplace.appcelerator.com/apps/5076?1735372176](https://marketplace.appcelerator.com/apps/5076?1735372176)

オープンソースのプロジェクトもgithubにありましたよ。
こちらは試していないのですが、手順がほぼ同じような感じだったので、もしかしたらこちらが本家かもしれませんね。

> **TiGMap**:
> [https://github.com/daisaru11/TiGMap](https://github.com/daisaru11/TiGMap)

## 組み込み手順
手順は [Google Maps for iOS のドキュメント](http://appcelerator.marketplace.assets.s3.amazonaws.com/downloads/5076/index.html.zip) 、または [TiGMap の README](https://github.com/daisaru11/TiGMap/blob/master/Readme.md) に詳しく書いてあります。

簡単に流れを説明すると・・・

1. Google Maps SDK for iOS をダウンロード
1. Google APIs Console で Google Maps SDK for iOS を有効にし API Access キーを取得する
1. (Marketplace で購入した) モジュールを配置
1. モジュール内の module.xcconfig に ダウンロードした Google Maps SDK for iOS へのパスを記述
1. Titanium Mobile のプロジェクトを作る（非Alloy）
1. Resources フォルダに GoogleMaps.bundle をコピーする
1. モジュールを使ってコードを書く

こんな感じでした。
各ドキュメントに詳しく書いてあるので、そちらを参照してください。

## Alloyから使う
Alloy **ではない** Titanium Mobile プロジェクトでは、上記手順によりiOS上で Google Maps を動かすことができました。ただ Alloy で動かそうとすると、以下の点が問題になってきます。

+ Resources フォルダに GoogleMaps.bundle をコピー
    + Alloy では Resources フォルダは自動生成なので、事前にコピーすることができない（消される可能性がある）

+ View の XML ファイルに記述できない
    + Controller に書かざるをえない

その辺りをなんとかしていきましょう

### GoogleMaps.bundleのコピー
**`app/assets` ディレクトリ** に **`GoogleMaps.bundle` をコピー** することで解決できます。
`app/assets`ディレクトリにあるファイルやフォルダは、実行時に`Resources`フォルダへコピーされます。あらためて言うまでもないかもしれませんね。

### View の XML を使う・・・というより Alloy に最適化する
僕はこんな感じにしてみました。プロジェクト内を色々と触るので、サンプルコードとして解説してみます。

#### APIキーをconfig.jsonで定義
Google APIs Console で取得した APIキー を定義する必要がありますが、せっかくなので`config.json`に書いてしまいましょう。
例では`global`に定義していますが、このモジュールは iOS 専用なので、`os:ios`に定義しても良いかもしれません。

```json
{
	"global": {
		"googlemapapikey": "WRITE YOUR API KEY HEAR"
	}, 
	"env:development": {}, 
	"env:test": {}, 
	"env:production": {}, 
	"os:ios": {}, 
	"os:android": {}, 
	"dependencies": {}
}
```

#### グローバル領域に GoogleMapsモジュールを定義
すべての処理に先立って実行される `alloy.js` を使って、グローバル領域に GoogleMapsモジュール を登録してしまいます。一緒にライセンスキーも設定してしまいましょう。

```javascript:alloy.js
Alloy.Globals.GoogleMaps = require('com.moshemarciano.googleMaps');
Alloy.Globals.GoogleMaps.licenseKey(Alloy.CFG.googlemapapikey);
```

#### View の定義は Namespace を使う
View の XML はこんな感じに定義します。当然ながら GoogleMapsモジュール をそのまま定義することはできないため、Namespaceを利用します。 `alloy.js` で GoogleMapsモジュール をグローバル領域に登録したのは、Namespaceで利用するためです。

```xml:index.xml
<Alloy>
	<Window id="window">
		<!-- GoogleMaps -->
		<GoogleMap ns="Alloy.Globals.GoogleMaps" id="map" />
	</Window>
</Alloy>
```

#### Alloy スタイルシート
これは通常と同じです。今回はこのように指定しました。

```javascript:index.tss
"#map": {
	width: Ti.UI.FILL,
	height: Ti.UI.FILL,
}
```

#### Alloy コントローラ
これも特に難しいところはありません。
せっかくなので、我が地元の名古屋駅を標準で表示するようにしてみました。

```javascript:index.js
// 名古屋駅へズームイン！
$.map.setCamera({
	latitude: 35.171072,
	longitude: 136.88158,
	zoom: 13
});

$.window.open();
```

#### 実行
ktkr！！
iOS 上で Google Maps が使えるようになったよ！！Alloyで！！

![Screen Shot 2013-07-29 at 12.46.15 copy.jpg](https://qiita-image-store.s3.amazonaws.com/0/9195/7a5d3b2d-3b26-8d91-d28b-22ffc5319d82.jpeg)