プッシュ通知周りの理解ができていなかったのでアプリに導入してみました。
目次
APNsキーをFirebaseに登録する
Apple DeveloperサイトでAPNs Authentication Key (.p8)を作成します。
Certificates, Identifiers & ProfilesのページのKeysからCreate a Keyを選択します。

KeyNameの入力とApple Push Notifications serviceにチェックを入れてからConfigureを選択します。

次の画面で利用する環境を選択します。開発時はSandbox、本番用はProductionを利用する必要があります。自分のアプリは既にリリース済みのためSandbox&Productionを選択します。
Key RestrictionはどのAPIで使うかを選択するものですがここではTeam Scoopedしか選択できなかったためこちらはそのままにしておきます。

Saveすると前の画面に戻るのでContinueを押して先に進みます。確認画面が出てくるのでRegisterをタップしてAPNsキーを登録します。

登録が完了するとAPNsキーをダウンロードすることができます。ダウンロードは1度しかできないため大切に保管しておきます。

ダウンロードしたAPNsキーを元にFirebaseのプロジェクト設定からアップロードします。

Xcode側で通知を許可する
次にアプリでプッシュ通知機能を利用するための設定を行います。
XcodeでTargetsを選択 > Sign&Capabilities > CapabilityからPush Notificationsを追加します。

次に開発・リリース用のApp IDにPush通知機能を許可する権限を追加します(デバイストークンの取得に必要なため)
追加後はプロビジョニングプロファイルを再インストールします。
もしAPNsキー(.p8)ではなくPush通知用の証明書を作成した場合はプッシュ通知用のプロビジョニングプロファイルを作成する必要が出てきます。
Firebase SDKの実装を行う
AppDelegateでSDKの初期化とAPNsにリクエストを行えるようにします
FirebaseApp.configure()
application.registerForRemoteNotifications()そうするとAPNsがデバイストークンを生成するので、下記のデリゲートメソッドで受け取ります。
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}Messagingを利用するにはFirebaseMessagingフレームワークをEmbedしてimportできるようにしておく必要があります。
SDKの実装は以上です。Firebaseがデバイストークンを元にAPNsに対して通知を送ってと依頼できるようになります。依頼を受け取ったAPNsは対象のユーザーに通知を送ることでアプリに通知が届きます。
通知をハンドリングする
UNUserNotificationCenter.current().delegate = selffunc userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound, .badge])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
completionHandler()
}willPresentについて
こちらはアプリがフォアグラウンドの場合に呼ばれるメソッドになります。フォアグラウンドの場合はデフォルトでは通知が表示されない仕様になっているのですが、completionHandlerで.bannerを返してあげることで通知を表示させることができます。.listを指定することで通知センターに通知を残すことも可能となります。
didReceiveについて
ユーザーが通知をタップした瞬間に呼ばれるメソッドとなります。このタイミングで通知の中に入っている情報を取り出して画面遷移を行ったりデータを読み込んだりします。バッジカウントを0にする処理もこのタイミングで記述します。
if let link = response.notification.request.content.userInfo["link"] as? String,
let url = URL(string: link) {
UIApplication.shared.open(url)
}
UNUserNotificationCenter.current().setBadgeCount(0)アプリの状態に対する挙動について
フォアグラウンド状態
willPresentで通知を表示する処理を行うと通知が表示される
↓
タップするとdidRecieveが呼ばれる
バックグラウンド状態
通知センターに通知が表示される
↓
通知をタップするとアプリに戻りdidRecieveが呼ばれる
未起動状態
通知センターに通知が表示される
↓
通知をタップするとアプリが起動する
↓
didRecieveが呼ばれる
通知を送信する
Messagingから新しい通知を作成すれば通知を飛ばすことが可能となります。繰り返しなどの設定ができるのもいいですね。

画面遷移用のリンクを設定したい場合はその他のオプションからカスタムデータとして登録する必要がありました。

FCMを利用すると簡単にアプリにプッシュ通知を飛ばすことが可能でした。設定してから30秒〜1分以内に通知が届くのもリアルタイムで良かったです。