Growth Push SDKのサポートが停止するらしいので、最新のGrowthbeat SDKに載せ変えようとしたらめちゃくちゃ苦戦した話

# 初めに

[CYBIRDエンジニア Advent Calendar 2016](http://qiita.com/advent-calendar/2016/cybird)
14日担当の@kanachaです。
女性向け恋愛シミュレーションの横串チームでアプリの開発・保守をしております。CYBIRD新卒入社2年目です。
13日は僕の同期(@cy-kenta-takahashi)さんの[UIPageViewControllerを使って漫画ビューアの見開き表示に対応した話](http://qiita.com/cy-kenta-takahashi/items/e8fa6a1316a916b7c9bd)でした。
ほう、漫画ビューアなんて作ってるんですね。

# 内容
https://sirok-growthbeat.amebaownd.com/posts/1313462
Growth Pushの管理ページを見ているとお知らせに赤文字で【重要】と書かれた記事が...(嫌な予感)

要約すると、古いGrowth Push SDKは使えなくなりますよ、最新版のSDKを導入してくださいね〜とのこと。
また「2016/12/21 (水)を以って、古いSDKはサポートを停止いたします。」とも書かれていたので、
holiday shutdownもあるしさっさと導入してリリースしてしまおう...と作業した結果、予想以上に苦戦してしまったお話をします。

# Growth Pushについて
どうやらGrowth pushのSDKにはいくつか種類があるらしく
・Growthbeat SDK 2.x.x
・Growthbeat SDK 1.x.x
・Growth Push SDK

途中からGrowth Push機能が統合されたGrowthbeat SDKというものになったようです。(弊社のアプリに導入されていたのは一番古い「Growth Push SDK」でした)
ありがたいことにサポートページには各verからの乗り換え手順がまとめてあり、ガイドも見やすく導入もお手軽でした。
旧SDKの実装コードも残っているので「まぁframeworkを載せ替えて、メソッド名をちょちょいと変えてやるだけでいけるのでは」と思いながら、
いつものよーにAd-Hoc版を作成し、deployGateにアップしてPushを飛ばしてみたところ
通知がこない...

他の端末で試してみたところ

iPhone5C　(OS 9.3.2)　届く
iPad2　(OS 8.4.1)　届かない
iPad mini　(OS 7.1.1)　届かない
iPhone4s　(OS 8.4.1)　届く
iPhone6plus　(OS 10.0.2)　届く
iPhone6　(OS 10.0.2)　届かない

むむむ...法則がわからん...

# 原因調査
飛ばない端末は、何故飛ばないのかを確認します。

まずは端末チェック。Pushの受け取り...は有効になっている。
Growth pushの管理ページを確認。Deviceの情報は...登録されている。
が、デバイストークンが空っぽ！これか！

Q&Aを確認すると
http://faq.growthbeat.com/article/60-push
「iOSの場合は、アプリの証明書の設定などが正しく行われていないと、デバイストークンが取得できずに、デバイストークンが空になる場合があります。この場合は、証明書の設定を見なおしてください。」
とのこと。

アプリのProvisioning Profileを作成し直し、念のためPush証明書も作り直して再登録。
これでいけるかと思いきや、トークンは空っぽのまま...

何が起こっているのか実機ビルドで確認することに。

```cpp
- (void) application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"error: %@", error);
}
```

このメソッドにブレイクポイントを張り、errorログを確認することでpushが送れない原因の特定を図る。

実行しようとしたら、Xcodeが接続した端末のiOSverに対応していなかったのでXcode8.1でビルドすることに。
すると、あれ...？普通にトークン入ってきた。しかもGrowrth Pushの管理ツールにデバイストークン渡ってる！！
もしかしてXcodeのバージョンの問題...？

# 対応

結論から申しますと、Xcode6.4にGrowthbeat SDKが対応していなかったというのが原因でした。
Xcode7系からプロジェクトにCapabilities→Push Notificationsという項目が追加されたようで、これが原因かもしれない...
Xcode7.3.1でもデバイストークンが取得できることを確認したので、一安心。
かと思いきや、Pushを飛ばしても端末がPushを受信しない、何故だ...


# 原因調査 その2
Growth pushの管理ページを確認
・Deviceの情報は登録されている
・トークンも渡っている
・デバイスのステータスがアクティブになっており、配信状況は「完了」
・プッシュ通知の配信の詳細は「成功」
・プッシュ通知のログを確認するが「success」で特に問題がないようだ
・端末側はPushの受け取りが有効になっていることは何度も確認した
やばい...マジでわからん...

管理ツールを見ながら途方に暮れていると、デバイスのステータスに「本番」の文字があることに気づく。
ん？本番...？今は実機デバッグで確認中...というかそもそも本番ってなんだ？

調査したところ、なんとiOSのデバイストークンには
Development版とProduction版が存在し、それぞれ全く異なった値になるとのこと。
では何故、管理ツールはデバイスを「本番」と認識したのか。

実装コードを確認したらそこに答えはありました...

```cpp
    [[GrowthPush sharedInstance] initializeWithApplicationId:GROWTH_PUSH_APP_ID
                                                credentialId:GROWTH_PUSH_APP_SECRET
                                                 environment:TEST_SERVER_FLAG ? GPEnvironmentDevelopment : GPEnvironmentProduction];
```
こちらGrowth pushの初期化メソッドになるのですが、
environment:という引数で環境を指定していたのでした。アホすぎる...

# 対応

つまり、どういうことが起きていたかというと
Growth pushの管理ツールにDevelopmentのデバイストークンを渡していたが、
Growth pushくんはAppleにそれをProduction向けでリクエストを送っていたようです。

まとめますと、デバッグビルドを行う際はDevelopmentの環境を、
リリースビルドを行う際はProduction環境を指定しないとPushが飛んでこないということなのでした。

これで解決！Ad-Hoc版をdeployGateに上げて、Distribution版をTestFlightに投げました。
さて、デバッグ端末からダウンロード...ん？ダウンロード失敗？
TestFlightもなんか変なエラーが出てる！！

![PicsArt_12-09-01.34.34.jpg](https://qiita-image-store.s3.amazonaws.com/0/101551/4b33a7cd-d22e-55be-afe3-d9d6eb39e1ed.jpeg)

# 原因調査 その3

http://qiita.com/Takumi_Mori/items/11b8d00f73163d890b24
http://qiita.com/hongmhoon/items/25abf462a8d7771e599b
こちらの記事に詳細がありました。

・Xcode7からTarget -> Capabilities -> Push NotificationsがONになっていないとPush機能が利用できない
・Xcode8.1でPush NotificationsをONにすると「projectname」.entitlementsに、developmentの項目が自動で追加される
とのことで、

「projectname」.entitlementsに、developmentの記述がある状態で、Ad-Hoc/Distribution向けにビルドを行いますと、
deployGateからはインストールができず、TestFlightへのアップロードにも失敗するといったエラーが起きてしまうわけです。

# 対応

対応策としまして、
developmentと追加された項目を削除したところ無事に通りました
(Xcode7.3.1でビルドしたので、本来ならば追加されないものなのですが、
 Xcode8.1でビルド検証をしていた時に追加されたまま残っていたようです)

もし、Xcode8系で開発する場合は、
「development.entitlements」「production.entitlements」というようにaps-environmentを分けたものを二つ作成してTargetごとに指定し、
環境によって使い分ける必要がありそうですね。

# おわりに
結局のところ、私の無知が招いた事件でした。(おかげでXcodeやらiOS Dev Center周りやらとても勉強になりました)
もし同じように悩んでいる方がいらっしゃれば、解決の糸口になるようであれば幸いです。
[CYBIRD エンジニア Advent Calendar] (http://qiita.com/advent-calendar/2016/cybird) 明日は、（@sakamoto_koji）さんの
「サブスクリプションのサーバサイド開発で得た知見」です。