Swift5でPUSH通知(リモートプッシュ通知)をFirebaseで導入する方法

# 初めに
今回はPUSH通知を導入する方法を記事にします。
**ローカル通知ではなくリモート通知です。**
サーバレスでやっていきますが、firebaseやニフクラがありますが、今回はfirebaseでPUSH通知を送る方法を展開します。
※前提として有料ライセンス(AppleDeveloper)に加入していること。
## 環境
Xcode 11.6
Swift5
##キーチェーンから証明書を取得
まず、キーチェンにアクセスしてCertificateで作成する際の必要なファイルを取得します。
「**キーチェーンアクセス**」→「**証明書アシスタント**」→「**認証局に証明書を要求**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/aeb51d3b-f88d-9530-50a1-cea05258c9af.png)
証明書アシスタントが出てくるので下記の情報を入力します。
ユーザのメールアドレス: developerのメールアドレス
通称:developerの名前
CAのメールアドレス:未記入
要求の処理:ディスクに保存
上記情報を入力した後、「**続ける**」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/58e3e83f-bf72-dcbe-0f59-fd5e663477ce.png)
あとはファイルの保存先を自分が分かる場所に指定して保存します。
##APNs用証明書の作成手順


### AppID作成
それでは[Developer](https://developer.apple.com)サイトに行きます。
「**Account**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/6a462121-e168-f3e4-5da5-53f56a7574b5.png)
「**Certificates, Identifiers & Profiles**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/2775ea14-7138-b9d6-2a6a-b468b89d45bc.png)
左メニューの「**Identifiers**」をクリック
「**＋**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/f2970c25-0bec-ecfb-b4f8-e1b00f766381.png)
「**App IDs**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/b75b4edb-07c2-c0c8-15c6-515cc9b0cfdb.png)
「**App**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/da13ff24-36df-4bde-dc12-0d72a91d0fff.png)
以下情報を入力します。
Description：アプリ名
Bundle ID: 作成中のバンドルID
CapabilitiesからPUSH通知にチェックを入れる。
上記情報を入力したら「**continue**」をクッリク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/c8e3d029-b22e-f418-47c6-e5631f9884b3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/e0dfe4db-8ecd-4d49-ab32-11499b3d6e2c.png)


### ProvisioningProfile作成
左メニューの「**Profiles**」をクリック
「**＋**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/de09f6f7-8c74-6009-984a-6ee65f4b90fe.png)
「**iOS App Development**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/e88da64f-7144-8451-8c51-a54977ac7037.png)
「**App ID:**」から「AppID作成」で作った物を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/6b4debc1-ace4-6a33-5596-9efa99b015af.png)
「**Select Certificates**」はSelecrALLで全て選択(問題なければ)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/a75fc7d9-68eb-9c93-e13f-d33850dfcac8.png)
登録した端末を選択、問題なければSelctAll
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/f421afc6-d64d-99ac-4f7d-e7106e8789e8.png)
「**Provisioning Profile Name**」に任意の名前を入れて「**Ganerete**」をクリック
あとはダウンロードするだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/bb7b7a12-92e9-6789-1fd4-c3836d5d1a4e.png)


### Certificate作成

左メニューの「**Certificates**」をクリック
「**＋**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/6124ef34-bcf1-b0cf-4723-2ea3d103e207.png)

「**Apple Push Notification service SSL**」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/93c5a760-f9a4-c5e9-a31d-b5e77444d153.png)

「**ChoseFile**」をクリックし、先ほどキーチェーンで作成したファイルを選び右上の「**Continue**」をクリック
あとはダウンロードをするだけ
ダウンロードした物をダブルクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/8ba6d7ce-f490-495b-b38b-21a404cff481.png)
ダウンロードした物を右クリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/1625bed3-ebb1-b176-f6d8-1569cb12ef39.png)
「**書き出す**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/cafc0952-c645-5b29-981d-8aceae275a71.png)
任意の場所を指定して保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/44ae7cbf-a0a9-cef8-3fb5-94d23e5fbbf3.png)
パスワードは未入力で「**OK**」をクリック
※証明書はあとで使うので忘れないところにおいて下さい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/e958f470-06cf-8f91-bd63-2d8220f51e8a.png)

##firebase登録
設定ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/0ad2c34c-0410-8093-916f-fc033b869e10.png)
「**プロジェクトを設定**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/cc7812c5-a2af-88a0-e389-11be846b963c.png)
「**クラウドメッセージング**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/b9ae617f-6481-a219-c5ec-dec0ed1bde48.png)
開発証明書の所で、
先ほどキーチェーンから書き出した物をアップロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/605c3b75-892d-ce79-216c-61e5dc878abf.png)

##Xcodeから設定する
Tagetの「**Signing & Capability**」から「**Provisioning Profile**」の設定をする
「**ProvisioningProfile作成**」で作った物を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/a09c39e6-497e-7e66-7c75-d7e53b90489f.png)
次に「**Capability**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/e5d09c02-a7c1-29bf-4abe-678724a7e5fc.png)
「**push**」検索欄に入力します。
「**Push**」をドラックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/2ce23a89-5d4d-f30a-4b64-cd05b103e384.png)
続いて「**BackgroundMode**」のドラックします。
BackgroundModeはチェックボックスがいっぱい出てくるので、「**Remote nortifications**」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/39c8e8b6-db50-8262-c7b2-19502b5ec476.png)

## 実装
まずAppDelegateを設定します。

```swift:AppDelegate.swift
import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {



     var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        //firebase初期化
        FirebaseApp.configure()

        application.registerForRemoteNotifications()
        Messaging.messaging().delegate = self
        UNUserNotificationCenter.current().delegate = self
        return true
    }
    
    // クラス内の他のdelegateメソッドと同じ階層に追記
     func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
        // Print message ID.
        if let messageID = userInfo["gcm.message_id"] {
            print("メッセージID: \(messageID)")
        }

        // Print full message.
        print(userInfo)
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // Print message ID.
        if let messageID = userInfo["gcm.message_id"] {
            print("メッセージID: \(messageID)")
        }

        // Print full message.
        print(userInfo)

        completionHandler(UIBackgroundFetchResult.newData)
    }
    

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }
    


}
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
    // 通知を受け取った時に(開く前に)呼ばれるメソッド
   func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
       let userInfo = notification.request.content.userInfo

       if let messageID = userInfo["gcm.message_id"] {
           print("メッセージID: \(messageID)")
       }

       print(userInfo)

       completionHandler([.alert])
   }

    // 通知を開いた時に呼ばれるメソッド
   func userNotificationCenter(_ center: UNUserNotificationCenter,didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
       let userInfo = response.notification.request.content.userInfo
       if let messageID = userInfo["gcm.message_id"] {
           print("メッセージID: \(messageID)")
       }

       print(userInfo)

       completionHandler()
   }
    
}
// MARK: - MessagingDelegate
extension AppDelegate: MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
    }
    
    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
        print("Received data message: \(remoteMessage.appData)")
    }
}

```
あとは任意の場所にPUSHのパーミッションダイアログ表示する

```swift:ViewController.swift
import UIKit
import UserNotifications

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        // プッシュ通知のパーミッションダイアログ表示
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in
            print("push permission finished")
        }
    }

}
```

##Cloud Messagingで通知を送る
新しい通知をクリックし、自分の送りたい情報を送ります。
するとピコンと通知が飛びます。
※実機で確認して下さい。（developerサイトで登録した端末で確認）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/f712ebd5-7f06-8826-2896-fd74f7a4e310.png)

#最後に
今回はFirebaseを使ったPUSH通知の記事を書きました。
PUSH通知は少しでも間違える通知が届かないのでゆっくり慎重に的確にやることをお勧めします！
最後までご覧いただきありがとうございます。
この記事がどなたかの役に立てれば幸いです！