iOS アプリをブルブルさせてみる

# ０．はじめに

ブルブルさせたいので、
既存のアプリにプッシュ通知(APNS)を実装してみます。

# １．Mac の キーチェーンアクセス から、CSR ファイルを作成する。

基本的には、以下の記事の手順に沿って、CSR ファイルを作成します。

* [プッシュ通知に必要な証明書の作り方2018 \- Qiita](https://qiita.com/natsumo/items/d5cc1d0be427ca3af1cb#1-csr%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90)
    * 「証明書アシスタント」ダイアログ
        * 証明書情報
            * 通称 : 英字で記入
            * 要求の処理 : 「ディスクに保存」を選択し「鍵ペア情報を設定」にチェック
* ※参考 :
    * [Xcode8を使ってiOSでPush通知をやってみた \- Qiita](https://qiita.com/toshihirock/items/00fd110ebff573121141)
    * [\[iPhone\] APNs プッシュ通知、デバイストークンの取得](https://i-app-tec.com/ios/apns-device-token.html)

# ２．既存の App ID に「Push Notifications (Development)」を設定する。

1. 以下のリンクにアクセスし、既存の App ID の情報を表示し、「Edit」ボタンを押下します。
    * [iOS App IDs \- Apple Developer](https://developer.apple.com/account/ios/identifier/bundle)
    * ![FireShot Capture 374 - iOS App IDs - Ap_ - https___developer.apple.com_account_ios_identifier_bundle.png](https://qiita-image-store.s3.amazonaws.com/0/161939/d80c2fbf-7214-6243-3940-e04ae49bd150.png)
1. 「Push Notifications」にチェックを入れ、「Development SSL Certificate」の「Create Certificate」ボタンを押下します。
    * ![FireShot Capture 375 - Settings - iOS App IDs - Apple Develo_ - https___developer.apple.com_accoun.png](https://qiita-image-store.s3.amazonaws.com/0/161939/99e9c9c6-a27a-3f31-468f-fb5c84fbad50.png)
1. 「Continue」ボタンを押下します。
    * ![FireShot Capture 376 - Add - iOS Cert_ - https___developer.apple.com_account_ios_certificate_create_.png](https://qiita-image-store.s3.amazonaws.com/0/161939/d060d4c3-ed4e-f944-f6db-13234f201ed9.png)
1. 「Choose File ...」ボタンを押下し、作成した CSR ファイルをアップロードします。
    * ![FireShot Capture 377 - Add - iOS Cert_ - https___developer.apple.com_account_ios_certificate_create_.png](https://qiita-image-store.s3.amazonaws.com/0/161939/9f1e5e47-b001-51b1-b18d-a1936a990604.png)
1. 「Continue」ボタンを押下します。
    * ![FireShot Capture 378 - Add - iOS Cert_ - https___developer.apple.com_account_ios_certificate_create_.png](https://qiita-image-store.s3.amazonaws.com/0/161939/f6b67c0b-7a82-d7e8-3d3b-634c3152977c.png)
1. 「Download」ボタンを押下し、CER ファイルをダウンロードし、「Done」ボタンを押下します。
    * <b><font color="red">※プッシュ通知を送る時に必要。</font></b>
    * ![FireShot Capture 379 - Add - iOS Cert_ - https___developer.apple.com_account_ios_certificate_create_.png](https://qiita-image-store.s3.amazonaws.com/0/161939/0421c67e-02fe-fceb-7e36-a4a59571ea2d.png)
1. 「Certificates」の一覧に作成された証明書が追加されます。
    * ![FireShot Capture 380 - iOS Certificates - Ap_ - https___developer.apple.com_account_ios_certificate_.png](https://qiita-image-store.s3.amazonaws.com/0/161939/01881ef1-82b5-d92e-e36c-57428f5c0dec.png)
1. 「Identifiers」の一覧を表示し、既存の App ID の情報を確認します。
    * ![FireShot Capture 381 - iOS App IDs - Ap_ - https___developer.apple.com_account_ios_identifier_bundle.png](https://qiita-image-store.s3.amazonaws.com/0/161939/6014e679-bf34-7868-56bd-74a55f160141.png)

# ３．既存の プロビジョニングファイルを更新する。

1. 以下のリンクにアクセスし、既存のプロビジョニングファイルの情報を確認します。
    * [iOS Provisioning Profiles \- Apple Developer](https://developer.apple.com/account/ios/profile/)
    * ![FireShot Capture 382 - iOS Provisioning Profiles_ - https___developer.apple.com_account_ios_profile_.png](https://qiita-image-store.s3.amazonaws.com/0/161939/879205d7-f1bf-c9e8-739d-d1ccb19e2969.png)
1. 以下のページを参考に、警告が表示されているプロビジョニングファイルを更新します。
    * [【続スクショ全部入り】iOSプロビジョニングプロファイルの更新 その2 \- Qiita](https://qiita.com/siglab/items/8c09674d33444a04640c)

# ４．P12 ファイルを作成する。

基本的には、以下の記事の手順に沿って、P12 ファイルを作成します。

* [プッシュ通知に必要な証明書の作り方2018 \- Qiita](https://qiita.com/natsumo/items/d5cc1d0be427ca3af1cb#7-apns%E7%94%A8%E8%A8%BC%E6%98%8E%E6%9B%B8p12-%E3%81%AE%E4%BD%9C%E6%88%90)
    * パスワード :
    * 手順には、「何も入力しない」とありますが、今回入力しました。

# ５．アプリの設定を変更する。

1. 以下のページの手順に沿って、設定を変更します。
    * [Xcode8を使ってiOSでPush通知をやってみた \- Qiita](https://qiita.com/toshihirock/items/00fd110ebff573121141#%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E8%A8%AD%E5%AE%9A)

# ６．アプリのコードを変更する。

## AppDelegate.swift

<ol>

<li>`import` に以下を追加。</li>

```swift
import UserNotifications
```

<li>以下のデリゲートを、継承元に追加。</li>

```swift
UNUserNotificationCenterDelegate
```

<li>`func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool` メソッドに以下を追加。</li>

```swift
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.alert, .sound, .badge], completionHandler: { (granted, error) in
            if error != nil {
                return
            }
            if granted {
                debugPrint("通知許可")
            } else {
                debugPrint("通知拒否")
            }
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        })
```

<li>以下のメソッドを追加。</li>

```swift
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let tokenParts = deviceToken.map { data -> String in
            return String(format: "%02.2hhx", data)
        }
        let token = tokenParts.joined()
        print("Device Token: \(token)")
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        print(userInfo)
        completionHandler(.noData)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print(userInfo)
        completionHandler(.noData)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to register for remote notifications with error: \(error)")
    }
```

* ※参考 :
    * [APNsとは？設定と実装方法の完全版！ \| Growth Hack Journal](https://growthhackjournal.com/ios-remote-push-notifications-in-a-nutshell/)
    * [Xcode8を使ってiOSでPush通知をやってみた \- Qiita](https://qiita.com/toshihirock/items/00fd110ebff573121141#%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E8%A8%AD%E5%AE%9A)
    * [<Swift>iOS 10 User Notifications Framework実装まとめ \- Qiita](https://qiita.com/mshrwtnb/items/3135e931eedc97479bb5)
    * [iOS10でプッシュ通知を実装してみた \- Goalist Developers Blog](http://developers.goalist.co.jp/entry/2017/08/31/175708)
    * [\[iPhone\] APNs プッシュ通知、デバイストークンの取得](https://i-app-tec.com/ios/apns-device-token.html)
    * [iOS Swift プッシュ通知を受け取ってからViewControllerに情報を渡す \- ボクココ](https://www.bokukoko.info/entry/2015/06/29/iOS_%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E9%80%9A%E7%9F%A5%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%81%A3%E3%81%A6%E3%81%8B%E3%82%89ViewController%E3%81%AB%E6%83%85%E5%A0%B1%E3%82%92%E6%B8%A1%E3%81%99)
    * [\[iPhone\] APNs プッシュ通知、デバイストークンの取得](https://i-app-tec.com/ios/apns-device-token.html)
    * [【Swift】いまさらですがiOS10でプッシュ通知を実装したサンプルアプリを作ってみた \- Qiita](https://qiita.com/natsumo/items/ebba9664494ce64ca1b8)
    * [iOSのPUSH通知\(APNS\)の特徴・ノウハウまとめ\(iOS 9まで対応\) \- Qiita](https://qiita.com/mono0926/items/df03c61adc56934e2e7a)

# ７．プッシュ通知の受信を確認する。

Pusher というアプリがあるみたいで、そちらを使います。

1. 以下のリンクの「README.md」の「Installation」の手順から、アプリをインストールします。
    * `$ brew cask install pusher`
    * [noodlewerk/NWPusher: OS X and iOS application and framework to play with the Apple Push Notification service \(APNs\)](https://github.com/noodlewerk/NWPusher)
1. アプリを起動すると通知の確認ダイアログが表示されるので、許可し、デバッグログからデバイストークンを確認します。
    * <img width="375" alt="2018-11-14_18-32-26_000.png" src="https://qiita-image-store.s3.amazonaws.com/0/161939/4822f6ba-a1a7-1c67-fb97-7bf32870b816.png">
1. Pusher を起動し、P12 ファイルをインポートします。
    * <img width="600" alt="スクリーンショット 2018-11-15 10.22.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/161939/834776e5-691d-a3ba-f9d2-792acc725178.png">
1. デバイストークンを入力し、「Push」ボタンを押下します。
    * <img width="600" alt="スクリーンショット 2018-11-15 10.19.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/161939/ea63ea1b-de1e-8269-b612-d0917fceaf6f.png">
1. アプリに通知が届くことを確認します。
    * <img width="375" alt="2018-11-14_18-36-10_000.png" src="https://qiita-image-store.s3.amazonaws.com/0/161939/7aea2c56-a500-e047-0a68-1ca4256823e0.png">
    * <font color="red"><b>アプリがフォアグラウンドの場合は、`application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)`のメソッドを通る形になるので、注意!!</b></font>

# ９９．ハマりポイント

* 特に大きなハマりは無かったですが…。
<br><br>
* この後、フォアグラウンド/バックグラウンド/未起動時などのそれぞれの状態での確認、通知の文言やレイアウトの調整、通知をクリックした後の動作など、諸々の対応が必要になるかと…。

# ＸＸ．まとめ

また、
Amazon SNS を使っての通知など、確認しようかと考えています。

ご参考になれば♪

* ※参考 :
    * [\[初心者向け\] プッシュ通知が送れないときに確認すること \- Qiita](https://qiita.com/k_teluki/items/b12502702234bd5d04dc)
    * [APNSで通知が飛ばない場合に考えられる問題 \- Qiita](https://qiita.com/0x0c@github/items/811fb70d0d2523968e50)
    * [iOS APNS開発\[サンドボックス\] vsプロダクション \[objective\-c\] \[iphone\] \| CODE Q&A 問題解決 \[日本語\]](https://code.i-harness.com/ja/q/1b3b58e)