(iOS)Nifty Cloud mobile backendを使ってリモートプッシュ通知をする方法

#はじめに
自分用のメモとして残しました。
Nifty Cloud mobile backendを使ってリモートプッシュ通知をする方法になります。

#Nifty Cloud mobile backendを使ってリモートプッシュ通知がされるまでの流れ
- Nifty Cloud mobile backend → Apple Push Notificationサービス（APNs）
 
Nifty Cloud mobile backendに登録されたデバイストークンをAPNsに送信する。

- APNs → デバイス → アプリで通知

APNsがデバイストークンから通知するデバイスを判断してプッシュ通知をする。

#手順

##その1「CSR Fileの作成」
キーチェーン → 証明書アシスタント → 証明局に証明書を要求...
<img width="834" alt="スクリーンショット 2017-05-01 15.03.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/e1fac32a-09f2-e77a-19bf-791156de15ac.png">

ディスクに保存を選択して続けるを押下。
<img width="615" alt="スクリーンショット 2017-05-01 15.04.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/c352200a-0817-eae6-1278-6e53cd404bcd.png">

保存場所を選択して保存を押下。
<img width="614" alt="スクリーンショット 2017-05-01 15.04.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/36f36c92-b79e-d11d-e3e6-685829863d19.png">

#Certificates(Production)の作成
Apple Developerサイト「Certificates, Identifiers & Profiles」を開く。
Certificatesの「All」の右上「＋」を押下。
Apple Push Notification service SSL (Sandbox & Production)を選択してContinueを押下。
<img width="737" alt="スクリーンショット 2017-05-01 15.57.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/fdcbed3a-83d8-428e-0609-8c0fa91c6015.png">

App IDを選択してContinueを押下。
<img width="737" alt="スクリーンショット 2017-05-01 14.50.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/95b3633e-eb94-846e-3cc7-7786f0b407a4.png">

Continueを押下。
<img width="731" alt="スクリーンショット 2017-05-01 14.50.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/6fad6025-1737-f688-8d60-0e247d267b25.png">

先ほど作成したCSR File(CertificateSigningRequest.certSigningRequest)をChoose File...から選択。
<img width="735" alt="スクリーンショット 2017-05-01 15.07.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/90f9e8d5-8c47-b8d1-19d1-2f958cd818b2.png">

Continueを押下。
<img width="736" alt="スクリーンショット 2017-05-01 15.07.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/77c33f66-6790-093b-ce9d-be53b69ca5a7.png">

Downloadを押下。
<img width="737" alt="スクリーンショット 2017-05-01 15.07.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/ba018a52-dc7e-07ce-940d-9e25d9c7750c.png">

#Certificates(Development)の作成
Apple Developerサイト「Certificates, Identifiers & Profiles」を開く。
Certificatesの「All」の右上「＋」を押下。
Apple Push Notification service SSL (Sandbox)を選択してContinueを押下。
<img width="734" alt="スクリーンショット 2017-05-01 15.57.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/d9b2c4c3-5efc-13d8-afc6-6f28e2a82f79.png">

App IDを選択してContinueを押下。
<img width="737" alt="スクリーンショット 2017-05-01 14.50.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/95b3633e-eb94-846e-3cc7-7786f0b407a4.png">

Continueを押下。
<img width="731" alt="スクリーンショット 2017-05-01 14.50.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/6fad6025-1737-f688-8d60-0e247d267b25.png">

先ほど作成したCSR File(CertificateSigningRequest.certSigningRequest)をChoose File...から選択。
<img width="735" alt="スクリーンショット 2017-05-01 15.07.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/90f9e8d5-8c47-b8d1-19d1-2f958cd818b2.png">

Continueを押下。
<img width="736" alt="スクリーンショット 2017-05-01 15.07.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/77c33f66-6790-093b-ce9d-be53b69ca5a7.png">

Downloadを押下。
<img width="736" alt="スクリーンショット 2017-05-01 16.02.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/94b57f40-49af-450e-a764-5e2e6a92f780.png">

#P12 File(Production)の作成
ダウンロードしたaps.cerをダブルクリック。(キーチェーンが開きます。)

Apple Push Services: xxxxxxを右クリック。
Apple Push Services: xxxxxxを書き出すを選択。
<img width="878" alt="スクリーンショット 2017-05-01 15.40.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/bbb6106b-e224-1e94-505c-20841b4c47e5.png">

場所を選択して保存を押下。
<img width="571" alt="スクリーンショット 2017-05-01 15.49.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/c04d76a4-417d-72be-bc65-6b3dbe871911.png">

パスワードは設定せず空白のままOKを押下。
<img width="444" alt="スクリーンショット 2017-05-01 15.49.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/29908481-006a-1dd6-b30e-ddb01336b158.png">

##その2「P12 File(Development)の作成」
ダウンロードしたaps_development.cerをダブルクリック。(キーチェーンが開きます。)

場所を選択して保存を押下。
(名前を「証明書dev.p12」などにしておくと良い。)

パスワードは設定せず空白のままOKを押下。

#App ID
Apple Developerサイト「Certificates, Identifiers & Profiles」を開く。
IdentifiersのApp IDsから対象アプリを選択。(未作成の場合は作成する。)

Push Notificationsを有効にする。
<img width="734" alt="スクリーンショット 2017-05-01 16.09.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/77ce1357-6ddf-6706-840d-725af14a87aa.png">

##その3「Provisioning Profileの再作成」
Provisioning Profilesから対象のProfileをEdit→Generateして再ダウンロードする。
ダウンロードしたProfileをダブルクリックする。
(iOS Distribution、iOS Developmentを再ダウンロードする)

##その4「Xcode」
CapabilitiesのPush Notificationsを有効にする。
<img width="741" alt="スクリーンショット 2017-05-01 16.34.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/59552128-c800-0043-216d-abef5d5c4b55.png">

Background ModesのRemote notificationsを有効にする。
<img width="739" alt="スクリーンショット 2017-05-01 16.44.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/a4c8c482-2704-529d-1e0a-00efd9b5a8d0.png">

##その5「AppDelegate」
AppDelegateのdidFinishLaunchingWithOptionsにUIApplication.shared.registerForRemoteNotifications()を追加。

```:didFinishLaunchingWithOptions
UIApplication.shared.registerForRemoteNotifications()
```

下記メソッドを追加。

```
extension AppDelegate {
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        //リモートプッシュ時の処理

        print("成功")
        completionHandler(.newData)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        ////リモートプッシュ失敗
        
        print(error)
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let installation = NCMBInstallation.current()
        installation?.setDeviceTokenFrom(deviceToken)

        saveInstallation(installation: installation)
    }

    private func saveInstallation(installation: NCMBInstallation?) {
        enum InstallationRegistErrorType: Int {
            case delete = 404001
            case duplication = 409001
        }

        installation?.saveInBackground { [weak self] (error) in
            if let error = error {
                switch InstallationRegistErrorType(rawValue: (error as NSError).code) {
                case .delete?:
                    //installationが削除された時　管理者の操作ミスなどによる削除
                    print("デバイストークン再登録開始")
                    self?.reRegistInstallation(installation: installation)
                case .duplication?:
                    //deviceTokenの重複エラー　アプリの再インストールが原因(ただiOS9からはデバーストークンが変わる)
                    print("デバイストークン更新開始")
                    self?.updateExistInstallation(installation: installation)
                default:
                    print("デバイストークン登録失敗", error)
                }
            }else {
                print("デバイストークン登録成功")
            }
        }
    }

    private func reRegistInstallation(installation: NCMBInstallation?) {
        installation?.objectId = nil

        saveInstallation(installation: installation)
    }

    private func updateExistInstallation(installation: NCMBInstallation?) {
        guard let deviceToken = installation?.deviceToken else {
            print("デバイストークン更新失敗")
            return
        }

        let query = NCMBInstallation.query()
        query?.whereKey(NCMBInstallationClass.deviceToken, equalTo: deviceToken)

        query?.getFirstObjectInBackground({ [weak self] (searchDevice, error) in
            if let error = error {
                print("デバイストークン更新失敗", error)
            }else if let searchDevice = searchDevice as? NCMBInstallation {
                installation?.objectId = searchDevice.objectId

                self?.saveInstallation(installation: installation)
            }else {
                print("デバイストークン更新失敗")
            }
        })
    }
}
```

##その6「Nifty Cloud mobile backendの設定」
プッシュ通知の許可を許可するを選択して保存。
<img width="776" alt="スクリーンショット 2017-05-01 16.50.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/1090d174-03f2-d147-2ceb-b634e14f94e8.png">

##その7「iOSプッシュ通知の証明書を選択」
証明書の選択を押下。
P12 File(Production)を選択する。
※リリース前の場合はP12 File(Development)を選択する。
※リリース後にP12 File(Production)に変更する。
<img width="775" alt="スクリーンショット 2017-05-01 16.50.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/9ad79ca3-7691-cd0b-bd02-761266f74312.png">

#テスト
Nifty Cloud mobile backendの新しいプッシュ通知を押下。
<img width="550" alt="スクリーンショット 2017-05-01 17.05.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/8a4822e3-2079-7e35-2ea8-c5c986d163cc.png">

iOS端末に配信するにチェックを入れてプッシュ通知を作成するを押下。
※テストのため、他は入力する必要はありません。
<img width="705" alt="スクリーンショット 2017-05-01 17.07.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/641110c1-2dcb-84a2-8fd8-5c30cd5744f0.png">

AppDelegateのdidReceiveRemoteNotificationが呼ばれたら成功です。

#さいごに
不備や疑問点などございましたら、お気軽にご連絡ください。