ウォークスルー後の通知許可とフォアグラウンド 通知を両立しようとしたら,うまくいかなかった件について


TL;DR

  • よくあるチュートリアルの後に通知許可の処理をしたらアプリ内通知が動かなかった
  • これをするときはappDelegateにフォアグラウンド処理を書いてもダメ
  • 通知許可のviewControllerにフォアグラウンド処理を書こう

何があったのか(前提条件)

  • appDelegateのapplication(_ application: UIApplication, didFinishLaunchingWithOptions)に通知許可の処理を書かない -> アプリ立ち上げでは通知許可は出さない
  • ウォークスルー終了後のメイン画面で通知許可を記述.
  • フォアグラウンド通知のためのfunc userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification:〜以下略)はappDelegateに書いていた.

実行環境

機材 バージョン
Xcode 11.5
iOS 13.5.1
Swift 5.2.4

解決方法

上に書いてあるとおり,appDelegateには通知系の処理を書かず,通知許可を取りたい画面のコードに,

MainViewController.swift
import UIKit
import UserNotifications

class MainViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //通知許可
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound, .badge]) { [weak self] (granted, _) in
            if granted {
                let center = UNUserNotificationCenter.current()
                center.delegate = self
            }
        }
    //~~~~~~
    (中略)
    //~~~~~~
}

extension MainViewController: UNUserNotificationCenterDelegate {
    //フォアグラウンド通知処理
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    willPresent notification: UNNotification,
                                    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        //通知とサウンドのみ
        completionHandler([.alert, .sound])
    }
}

と記述する.

最後に

なんでこんな仕様なんだろう・・・
原理や「お前の勘違いや」,「もっとこうすべき」などのご指摘がございましたらコメントにてよろしくお願いいたします.