MapBox SDK for Xamarinを試してみた (1) とりあえず動かしてみる(iOS実機は動かない)

[MapBox](https://www.mapbox.com/)のOpenGL版[iOS](https://www.mapbox.com/ios-sdk/)/[Android](https://www.mapbox.com/android-sdk/) SDKが出揃った昨今ですが、Xamarinが早速[コンポーネントストア](https://components.xamarin.com/view/mapboxsdk)にポーティングしてきました。
早速、ちょっとサンプルを動かしてみようと思います。
# 事前準備
MapBox SDKを使うには、MapBoxのAPI Keyが必要です[^1]。
[^1]: 本記事を書き始めてから気付きましたが、もしかしたらAPI Keyは背景地図にMapBoxの地図タイルを使う時のみ必要で、独自地図タイルを使う際等は不要なのかもしれません。が、とりあえずの動作テストでは必要という前提で進めます。
MapBoxのAPI Keyを取得するには、MapBoxのページの右上のSignUpより開発者登録します。
![MapBox](https://qiita-image-store.s3.amazonaws.com/0/10108/2ec04e8e-b7c1-4c81-76fa-1fab300d69c0.png)
無料で使うため、会員レベルはStarterにします。月50000ビューまで、無料で地図タイルを利用できます[^2]。
[^2]: 地図タイルの利用制限のはずなので、[地理院地図](http://maps.gsi.go.jp/)のように他に使える地図を背景に使う場合、無料でずっと使える...はずです。なのでもしかすると、その場合はAPI Keyは不要なのかもしれませんが、次回以降の記事で確かめます。
![SignUp](https://qiita-image-store.s3.amazonaws.com/0/10108/b7ba17db-6da7-1d9d-8912-69ba57146c87.png)
会員になってダッシュボードを開き、「Apps」と書かれたタブを選びます。そこにある、「sk.」から始まる文字列が、ネイティブアプリ用のAPI Keyとなります。
![ダッシュボード](https://qiita-image-store.s3.amazonaws.com/0/10108/9b11349b-8bf1-c09d-e4d3-8b0d803c7318.png)
このAPI Keyが動作に必要ですので、書き留めておきます。
# サンプルプログラムの取得
サンプルプログラムを動作させるには、Xamarinで何か適当なソリューションを作り、そこからコンポーネントにMapBox SDKを追加します。
SDKのダッシュボードでSamplesタブを選ぶと、Sampleを取得できるボタンがあるので、そこをクリックすると、Android/iOS双方のサンプルプログラムが入手できます。
![コンポーネントダッシュボード](https://qiita-image-store.s3.amazonaws.com/0/10108/13751b32-9c2e-03a7-c738-e1826bc451e3.png)
# Android版サンプルの動作確認
Android版の場合、API KeyはレイアウトXML上で指定しますが、サンプルプログラムのレイアウトXMLは

```xml:Resources/layout/Main.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.mapbox.mapboxsdk.views.MapView
        android:id="@+id/mapview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        mapbox:accessToken="@string/mapboxAccessToken" />
</LinearLayout>
```
のようになっているので、Resources/values/String.xmlの中にAPI Keyを記載します。

```xml:Resources/values/String.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
	<string name="app_name">Mapbox Sample</string>
	<string name="mapboxAccessToken">sk.eyJ1I...</string>	
</resources>
```
これで実行すれば、実機でも普通に動きます。コンパイルエラーが出る場合は、Target Android VersionやMinimum Android Version等が自分の開発環境と合っているか確認しましょう。
![Android動作状況](https://qiita-image-store.s3.amazonaws.com/0/10108/bc4dfcfe-3b07-2467-b78f-67b2be605ad5.png)
# iOS版サンプルの動作確認
あっさりと動いたAndroid版に比べ、iOS版はデフォルトの環境設定がいろいろ問題がありあっさりとは動きません。
また、結論を言うとシミュレータでは動きますが、実機（iPhone5S+iOS9.1）では動きません。
バグなのか、設定不足なのかわかりませんが、コミュニティに報告などもしつつ、何か分かれば続報を書きます。
### API Keyの置き換え
iOS版の場合、API Keyは**AppDelegate.FinishedLaunching**の中で指定します[^3]。

```csharp:AppDelegate.cs
        const string MAPBOX_ACCESS_TOKEN = "sk.eyJ1I...";

        public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
        {
            if (MAPBOX_ACCESS_TOKEN == "YOUR-ACCESS-TOKEN") {
                new UIAlertView ("Change Access Token", "You need to change the MAPBOX_ACCESS_TOKEN to your own token from MapBox!", null, "OK")
                    .Show ();
            }

            // Set your own Access Token 
            AccountManager.AccessToken = MAPBOX_ACCESS_TOKEN;

            return true;
        }
```
上記のMAPBOX_ACCESS_TOKEN定数の値を変更します。
[^3]: **Info.plist**の中の**MGLMapboxAccessToken**キーの値として入れる方法もあるようですが、サンプルプログラムがこうなっていたのでそちらで進めます。

### ライセンスがIndieの場合はEnable profilingをオフにする
この設定後、シミュレータで実行しようとすると、Indieライセンスの場合、以下のようなエラーが出ます。
![ライセンスプロンプト](https://qiita-image-store.s3.amazonaws.com/0/10108/4442fe74-972f-abea-7614-47536b970a47.png)
これは、サンプルプログラムのデフォルト設定がEnable Profilingになっているのですが、同機能がBusinessライセンス以上でしか有効化されていないためです。
これを解除するには、サンプルプロジェクトのプロジェクトオプションを表示し、iOS BuildタブのEnable profilingをオフにします。この項目は、プラットフォームiPhone/iPhone Simulator双方にありますので、両方でオフにします。
![EnableProfilingをオフに](https://qiita-image-store.s3.amazonaws.com/0/10108/a57a2e93-6561-87ff-a5f9-0c077094abce.png)
### シミュレータではここまでで動作する
シミュレータ環境では、ここまでで動作します。
![iOSシミュレータ動作状況](https://qiita-image-store.s3.amazonaws.com/0/10108/77f263d3-6606-81ad-b18e-9f8449afea45.png)
### 64ビット環境のみでのコンパイルに変更する
実機環境向けでコンパイルしようとすると、まずぶつかるのが、静的ライブラリが見つからないといったエラーです（すみません、なぜか記事書いている最中に再現しようとしてもしなくなってしまったので、エラー詳細を記載できませんが）。
このエラーは、[コンポーネントストア](https://components.xamarin.com/view/mapboxsdk)の対応プラットフォームを見るとios-64としか書かれていないのに、コンパイルアーキテクチャが**ARMv7s+ARM64**になっていたので、**ARM64**だけにしてやると回避できました。
![ARM64だけにする](https://qiita-image-store.s3.amazonaws.com/0/10108/d63139bb-51a1-fa06-0659-0843c226923e.png)
### -ObjCコンパイルオプションをつける
上記実行後コンパイルを進めようとすると、ビルドは完了しますが、デバグ起動中に以下のようなエラーを吐いて落ちます。

```shell-session:エラー出力
MapboxSampleiOS[3635:1365466] -[NSProcessInfo mgl_isInterfaceBuilderDesignablesAgent]: unrecognized selector sent to instance 0x156609bf0
```
これはググってみたところ、コンパイルオプションに-ObjCをつければ解決するようです。
![-ObjCコンパイルオプション](https://qiita-image-store.s3.amazonaws.com/0/10108/dc06c3ed-d7f0-4e85-cd17-6da9ace038e7.png)
上記の赤丸のところに、

```shell-session:コンパイルオプション
-gcc_flags "-ObjC"
```
を記載するとコンパイルが通るようです。
### MGLAnnotationクラスがないと言われる（未解決）
さらに実機動作確認すると、以下のエラーが発生します。

```shell-session:エラー出力
Wrapper type 'Mapbox.Annotation' is missing its native ObjectiveC class 'MGLAnnotation'.
```
![エラー画面1](https://qiita-image-store.s3.amazonaws.com/0/10108/efa71837-7339-32de-84df-1e419ed45f9a.png)
![エラー画面2](https://qiita-image-store.s3.amazonaws.com/0/10108/74f40497-fd49-70ca-b43b-f4d4d3537615.png)
これをググってみると、こういう感じのエラーが出るときは前節でのコンパイルオプションにさらに追加して

```shell-session:コンパイルオプション
-gcc_flags "-ObjC -lc++ -lstdc++"
```
にすれば直るという情報もあったりしたのですが、今回の例では直りませんでした。

これについては引き続き調査中ですが、どうにもバグくさいので、コミュニティへの報告等もしつつ解決したいと思います。


以上、とりあえずMapBox SDK for Xamarin、触ってみた結果の報告でした。