SwiftでFirebaseを使ってNotificationを送ってみた（が、色々詰まった話）

若干話題に乗り遅れた感がありますが、SwiftでFirebaseを使ってNotificationを送ってみました。
ところどころ詰まったので、詰まったポイントを中心に記載しました。

# 環境
* Swift: 2.2
* CocoaPods: 1.0.0.rc.2
* iOS: 8.0〜

# 1. FireBaseプロジェクトを作成
https://console.firebase.google.com/
googleアカウントでログインしてプロジェクトを作成する or 既存のプロジェクトを選択する

<img width="1489" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/26102/cf235992-b689-f2a8-2566-6a11eeebb52f.png">

# 2. Xcodeプロジェクトを作成
適当な名前でXcodeプロジェクトを作成して下さい。

# 3. 「iOSアプリにFireBaseを追加」を選択

<img width="1489" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/26102/4cb1fce3-a5ff-cd30-9fe7-cbc832eaf599.png">

表示される手順に沿って初期設定を実施。

<img width="1491" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/26102/62b7a8f2-63c5-94dd-0e9e-da7b8d223147.png">

手順４の「初期化コードを追加」で詰まったので下記参考にPodfileを修正。CocoaPodsのバージョンの問題？それとも公式の手順の更新漏れ？

[iOS - Firebase error: Use of unresolved identifier FIRApp running supplied code](http://stackoverflow.com/questions/37328508/ios-firebase-error-use-of-unresolved-identifier-firapp-running-supplied-code)を参考にPodfileを修正。
ついでに、Messaging用のライブラリも入れておく。

```file:Podfile
...
pod 'Firebase/Core'
pod 'Firebase/Messaging'
...
```

# 4. APNs 証明書の準備
Notificationを送信するにはAPNs 証明書が必要なため準備します。

## 4-1APNs 証明書を作成
[Provisioning APNs SSL Certificates](https://firebase.google.com/docs/cloud-messaging/ios/certs#create_the_ssl_certificate)
[「APNs 証明書」の検索結果 - Qiita](http://qiita.com/search?q=APNs+%E8%A8%BC%E6%98%8E%E6%9B%B8)
あたりの手順を参考に証明書を作成して下さい。

## 4-2. APNs 証明書をアップロード
作成した証明書をFirebaseにアップロードして下さい。

<img width="1487" alt="4.png" src="https://qiita-image-store.s3.amazonaws.com/0/26102/11a8abd8-62d4-d731-6070-e16248ebdeb1.png">

<img width="1492" alt="5.png" src="https://qiita-image-store.s3.amazonaws.com/0/26102/10216fc2-b782-66d9-2e18-48761f10329b.png">


# 5. アプリの設定

単純にNotificationを送るだけであれば、FireBaseの初期化時 FIRApp.configure() によしなに設定しておいてくれるので、特にコードを書く必要はないそうです。親切設計ですね。

・・・のはずが、notificationが受信できない。

Xcodeのコンソールを見てみると

```
<FIRInstanceID/WARNING> Failed to fetch APNS token Error Domain=com.firebase.iid Code=1001 "(null)"
```

てなエラーが出てtokenの取得に失敗している模様。

["Failed to fetch APNS token Error Domain=com.firebase.iid Code=1001"](https://www.google.co.jp/search?q=%22Failed+to+fetch+APNS+token+Error+Domain%3Dcom.firebase.iid+Code%3D1001%22&oq=%22Failed+to+fetch+APNS+token+Error+Domain%3Dcom.firebase.iid+Code%3D1001%22&aqs=chrome..69i57.1134j0j9&sourceid=chrome&ie=UTF-8)で検索しても2件しか引っかからない・・・。

[こちら](http://stackoverflow.com/questions/37333177/cloud-messaging-handing-terminate-app)の回答を参考に自分でnotificationの設定をしてみた。
とりあえずは動くようにはなったものの腑に落ちない。

あ、あと、うっかりシミュレータで起動すると下記のエラーが出ました。notificationは実機じゃないと受信できないので、実機に向けて向けてビルドしましょう。

```
<FIRInstanceID/WARNING> Failed to fetch APNS token Error Domain=NSCocoaErrorDomain Code=3010 "REMOTE_NOTIFICATION_SIMULATOR_NOT_SUPPORTED_NSERROR_DESCRIPTION" UserInfo={NSLocalizedDescription=REMOTE_NOTIFICATION_SIMULATOR_NOT_SUPPORTED_NSERROR_DESCRIPTION}
```

# 6. notificationを送ってみる

さて、ようやく準備が出来たのでnotificationを送ってみましょう。が、1点注意点があります。

> Note: unless you first add message handling logic to your client app as described in the next section, some users may not receive the notifications you send. This includes any users who have your app in the foreground on the device.
> 参考：[Send a Notification to a User Segment on iOS](https://firebase.google.com/docs/notifications/ios/console-audience#send_a_message_from_the_notifications_console)

公式のドキュメントには上記のように記載があり、ここまでの実装状況ではアプリがforegroundにあるときに受けとったメッセージはハンドリングしていないので、後述するようなロジックを追加してあげる必要があります。

まずは、アプリがforegroundじゃない状態でnotificationを送ってみましょう。
実機にアプリをインストールして、通知を許可した後、Firebaseのコンソールからnotificationを送ります。

<img width="1517" alt="スクリーンショット_2016-05-23_22_49_36.png" src="https://qiita-image-store.s3.amazonaws.com/0/26102/24e42ffc-ede0-b8ea-6ad7-a8eba55c99ae.png">

<img width="1516" alt="スクリーンショット_2016-05-23_22_50_34.png" src="https://qiita-image-store.s3.amazonaws.com/0/26102/8559f0d3-614c-ee05-84d5-2268bfa9d61e.png">


とりあえず、メッセージ文とターゲットだけ決めれば送信できます。

## 6-1. ロック画面の時に送信

![2016-05-23_19_55_12.png](https://qiita-image-store.s3.amazonaws.com/0/26102/8a9acea1-4bfb-6235-63bc-ab7572a0b5c7.png)

## 6-2. アプリがbackgroundにある時に送信

![2016-05-23_22_40_55.png](https://qiita-image-store.s3.amazonaws.com/0/26102/feb642c1-6050-a75f-1401-e384360fdd02.png)

## 6-3. アプリ終了後に送信

![2016-05-23_22_41_43.png](https://qiita-image-store.s3.amazonaws.com/0/26102/6114e5b6-7167-8391-2242-1c45c01dc57b.png)

ふむ、良いですね。

# 7. 受信したnotificationの内容をアプリ上で扱うには

アプリがforegroundにある時に受信したメッセージの内容を扱いたい場合には下記のような感じでAppDelegateの application:didReceiveRemoteNotification を実装すればOKです。
今回はとりあえずnotificationを受信したらalertを表示するようにしてみました。

```
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    if application.applicationState == .Active {
        if let aps = userInfo["aps"] as? NSDictionary {
            if let alert = aps["alert"] as? String {
                let alert = UIAlertController(title: "受け取ったメッセージは", message: alert, preferredStyle: .Alert)
                alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
                self.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
            }
        }
    }
}
```

さて、上記を実装して、アプリがforegroundにある時に、再度notificationを送ってみましょう。

![2016-05-23_19_46_39.png](https://qiita-image-store.s3.amazonaws.com/0/26102/9ffdb29a-183c-7ef7-6cad-e2397b7b8932.png)

うん、良さそうですね。

無料で簡単にいくらでもnotificationが送れるらしい、ということで飛びついてみたら、公式のドキュメント通りにやってみたつもりが、自分の書き方が悪いのか、設定が抜けてるのか、意外と引っかかった部分が多かったです。
FIRApp.configure() の実行だけでnotificationを送れた方がいたら、環境や手順などを公開されることを期待してます！