[iOS 10] 画面上部または通知センター上に表示された通知がタップされたときの処理を実装する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。モバイルアプリサービス部の平屋です。前回の記事に引き続き、iOS 10 で追加された「User Notifications framework」のクラスを使用した実装を紹介します。

本記事では、画面上部または通知センター上に表示された通知がタップされたときの処理の実装を紹介します。

本記事は Apple からベータ版として公開されているドキュメントを情報源としています。 そのため、正式版と異なる情報になる可能性があります。ご留意の上、お読みください。

実装

deprecated になったメソッドについて

iOS 9 以前の場合、UIApplicationDelegate の以下の 2 つのメソッドを使用していましたが、iOS 10 で deprecated になりました。

optional public func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
optional public func application(_ application: UIApplication, didReceive notification: UILocalNotification)

上記のメソッドの代わりになるメソッドが UNUserNotificationCenterDelegate に用意されているので、そのメソッドの使い方を解説していきます。

通知がタップされたときの処理を実装

任意のオブジェクトを UNUserNotificationCenter のデリゲートにして、userNotificationCenter(_:didReceive:withCompletionHandler:) メソッドを実装します。

// デリゲートを設定
UNUserNotificationCenter.current().delegate = self
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: () -> Void) {
    // 通知の情報を取得
    let notification = response.notification

    // リモート通知かローカル通知かを判別
    if notification.request.trigger is UNPushNotificationTrigger {
        print("didReceive Push Notification")
    } else {
        print("didReceive Local Notification")
    }

    // 通知の ID を取得
    print("notification.request.identifier: \(notification.request.identifier)")

    // 処理完了時に呼ぶ
    completionHandler()
}

response 引数から、UNNotification を取れるので、リモート通知かローカル通知かを判別することができます。

また、UNNotificationUNNotificationRequest をプロパティに持つので、通知の ID からどの通知がタップされたかを判別することができます。

completionHandler

userNotificationCenter(_:didReceive:withCompletionHandler:) メソッドの 3 つ目の引数 completionHandler について、リファレンスを読むと「You must execute this block from your method, and should call it as quickly as possible. 」と書いてありました。

メソッド内の処理の最後に completionHandler() を呼ぶようにします。呼ばないとどうなるかをためしてみると、warning のログがコンソールに表示されました。

Warning: UNUserNotificationCenter delegate received call to -userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: but the completion handler was never called.

アプリがメモリ上にあるかどうかによる違い

通知がタップされた時に、アプリがメモリ上にある場合でもない場合でも、userNotificationCenter(_:didReceive:withCompletionHandler:) メソッドを使用して、通知がタップされたときのイベントを取得できます。

しかし、アプリがメモリ上にない状態で通知がタップされたイベントを取得したい場合は、UNUserNotificationCenter のデリゲートを割り当てるタイミングをよく考える必要がありそうです。

試しに、AppDelegatedidFinishLaunchingWithOptions メソッド内で UNUserNotificationCenter のデリゲートにして、AppDelegate にデリゲートメソッドを実装したところ、上手くいきました。

さいごに

本記事では、画面上部または通知センター上に表示された通知がタップされたときの処理を実装を紹介しました。

「通知がタップされたときに特定の画面に遷移させる」といった仕様を実現する時に必須の実装になりますね。通知がリモートかローカルかによらず、同じメソッドでハンドリングできるのは良いなと思いました。

今後も User Notifications framework のクラスを試していきます!