Swift・iOS

Swiftを中心に学んだことを記録に残すブログです。技術に関係ない記事もたまに書いています。

【SwiftUI】Firebase Cloud Messagingで受信したプッシュ通知の内容をSwiftUIのViewで利用する

 

はじめに

Firebase Cloud Messagingで受信したプッシュ通知の内容をSwiftUIのViewで利用する実装について記事に残します。

※Firebase Cloud Messagingの導入に関しては、以下の記事に記載しています。

【Firebase Cloud Messaging】導入の手順 - Swift・iOS

 

開発環境

  • macOS Catalina 10.15.7
  • Xcode 12.2
  • Swift 5.3.1
  • CocoaPods 1.10.0
  • FirebaseMessaging 7.3.0

 

本題

AppDelegate.swiftのuserNotificationCenter(_:didReceive:withCompletionHandler:)メソッドを以下のように実装。通知が選択された時に通知のペイロードを送る。

※参考:【Firebase Cloud Messaging】受信したメッセージを処理する - Swift・iOS

AppDelegate.swift

// 通知を選択した時の挙動
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo
    NotificationCenter.default.post(name: Notification.Name("didReceiveRemoteNotification"),
                                            object: nil, userInfo: userInfo)
        
    completionHandler()
}

※通知のペイロードは以下。("url"はカスタムキーです。)

[
    AnyHashable("google.c.a.c_id"): xxxxxxxxxxxxxxxxxxx,
    AnyHashable("google.c.a.e"): 1,
    AnyHashable("gcm.message_id"): xxxxxxxxxxxxxxxx,
    AnyHashable("url"): "{URL}",
    AnyHashable("google.c.sender.id"): xxxxxxxxxxxx,
    AnyHashable("aps"): {
        alert =     {
            body = "{プッシュ通知の本文}";
            title = "{プッシュ通知のタイトル}";
        };
        "mutable-content" = 1;
    },
    AnyHashable("google.c.a.ts"): xxxxxxxxxx,
    AnyHashable("google.c.a.udt"): 0,
    AnyHashable("gcm.n.e"): 1
]

 

onReceive(_:perform:)を使ってViewで通知を受け取る。以下の実装は、通知のペイロードに含まれるタイトルとURLを出力しているサンプル。

ContentView.swift

.onReceive(NotificationCenter.default.publisher(for: Notification.Name("didReceiveRemoteNotification"))) { notification in
    if let userInfo = notification.userInfo, let aps = userInfo["aps"] as? [AnyHashable: Any], let alert = aps["alert"] as? [AnyHashable: Any], let title = alert["title"], let urlString = userInfo["url"] {
        print(screenCoordinator.title)
        print(screenCoordinator.urlString)
    }
}

 

通知の内容をViewで利用するメリットとしては、以下のようにTabViewで通知を受け取り、画面遷移を扱うScreenCoordinatorクラスの値を変更することで、プッシュ通知を選択したときの画面遷移を実装できることなどが考えられる。

ContentView.swift

struct ContentView: View {
    @EnvironmentObject var screenCoordinator: ScreenCoordinator
    
    var body: some View {
        TabView(selection: $screenCoordinator.selection) {
            // 実装省略
        }
        .onReceive(NotificationCenter.default.publisher(for: Notification.Name("didReceiveRemoteNotification"))) { notification in
            if let userInfo = notification.userInfo, let aps = userInfo["aps"] as? [AnyHashable: Any], let alert = aps["alert"] as? [AnyHashable: Any], let title = alert["title"], let urlString = userInfo["url"] {
                screenCoordinator.selection = 2
                screenCoordinator.title = title as? String ?? ""
                screenCoordinator.urlString = urlString as? String ?? ""
            }
        }
    }
}

 

おわりに

プッシュ通知を起点とした画面遷移なども試したら記事にしたいと思います。

 

参考