【Swift】ローカル通知が受信されたかを知る方法

どうも、ねこきち(@nekokichi1_yos2)です。

 

今回は、ローカル通知の受信を検知する方法を載せます。

 

ローカル通知のデリゲートメソッドについて

 

ローカル通知には、

  • willPresent()
  • didReceive()

のデリゲートメソッドしかありません。

 

しかも、上記の2つはそれぞれ、

  • フォアグラウンドで通知を受け取った時
  • 通知をタップした時

でしか実行されません。

 

もし、ユーザーがアプリをタップした場合、デリゲートメソッドに引っかからず、アプリを起動した時、通知が受信された時に実行したい処理がスルーされてしまいます。

(プッシュ通知なら、受信時の処理を実行できるだろうが、今回は却下。)

 

そこで登場するのが、getDeliverdNotification()、です

 

getDeliverdNotification()を使う

 

ドキュメントでは、NotificationCenterに登録された通知の一覧を返すメソッド、だそうです。

 

書き方は、以下の通り。

UNUserNotificationCenter.current().getDeliveredNotifications { (notification) in
}

 

クロージャの引数をprint()で出力すると、受信された通知の詳細が出ます。

f:id:nekokichi_yos2:20201231213249p:plain

 

また、取得する値は、UNNotification型の配列です。

f:id:nekokichi_yos2:20201231213438p:plain

 

例えば、配列のプロパティであるisEmptyを利用すれば、

  • true:受信されてない
  • false:受信された

により、通知が受信された時の処理を実装できます。

UNUserNotificationCenter.current().getDeliveredNotifications { (notification) in
    if notification.isEmpty {
        // 受信してない
    } else {
        // 受信した
    }
}

 

結果、ローカル通知のデリゲートメソッドでは拾えなかった、

のユーザーアクションにも対応できます。

 

getDeliverdNotification()でできること

 

まとめると、

  • ローカル通知の詳細を取得できる
  • ローカル通知が受信されたかがわかる
  • sceneDidBecomeActive()と併用すれば、アプリの直接起動でも、受信状態の分岐ができる

 

ソースコード

  

import UIKit

class UNUserNotificationTest: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let content = UNMutableNotificationContent()
        content.title = "通知"
        content.body = "受信しました"
        content.sound = .default
        // 5秒後に通知
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        let request = UNNotificationRequest(identifier: "notification", content: content, trigger: trigger)
        let center = UNUserNotificationCenter.current()
        center.add(request) { (error) in
            if let error = error {
                print(error)
            }
        }
    }

}


import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        //ローカル通知
        UNUserNotificationCenter.current().requestAuthorization(
            options: [.alert, .sound, .badge]){
            (granted, _) in
            if granted{
                UNUserNotificationCenter.current().delegate = self
            }
        }
        return true
    }

}



import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }
    }

    // バックグラウンド -> フォアグラウンド、で実行
    func sceneDidBecomeActive(_ scene: UIScene) {
        UNUserNotificationCenter.current().getDeliveredNotifications { (notification) in
            if notification.isEmpty {
                // 受信してない
            } else {
                // 受信した
                print("受信しました")
            }
        }
    }

}