SwiftUI 处理在终止状态下点击的推送通知

SwiftUI handle push notifications tapped in a terminated state

我有一个带有聊天功能的 SwiftUI 应用程序,它使用 Firebase 作为其后端和 Cloud Function 来侦听新的聊天消息并通知用户。当用户在相应的聊天室之一中收到新的聊天消息时,Cloud Function 会向登录用户的所有设备发送通知。为了导航,我创建了一个 NotificationManager,如果用户点击了通知,它可以帮助应用程序在应用程序的嵌套视图中导航。

一切正常,但是当用户在应用程序终止后点击通知时,导航不起作用。我想这是因为在用户恢复之前导航被点击并且它的属性被更改......?我试图寻找与 UIKit 相关的解决方案(因为我没有找到任何与 SwiftUI 相关的解决方案),但还没有找到合适的解决方案。

在我的 AppDelegate 上面:

weak var notificationManager: NotificationManager?

用户点击通知:

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID from userNotificationCenter didReceive: \(messageID)")
        }
        
        print("*** NotificationInfo: \(userInfo) ***")
        let info = userInfo as NSDictionary
        guard let chatID = info.value(forKey: "chatID") as? String else { return } // retrieving the ChatID from notification payload
        
        
        // Navigate to the room of the chatID when chat notification is tapped
        
        
        notificationManager?.pageToNavigationTo = 1 // navigate to messages view
        notificationManager?.recievedNotificationFromChatID = chatID // navigate to correct chat
        
        
        completionHandler()
    }

生命周期:

@main
struct VitaliiApp: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    @StateObject var session = SessionStore()
    let notificationManager = NotificationManager()
    
    func setUpdNotificationManager() {
        appDelegate.notificationManager = notificationManager
    }
    
    var body: some Scene {
        WindowGroup {
            
            ContentView()
                .environmentObject(session)
                .environmentObject(notificationManager)
                .onAppear {
                    setUpdNotificationManager()
                }   
        }
       
        
    }
}

NotificationManager:

class NotificationManager: ObservableObject {
    static let shared = NotificationManager()
    @Published var pageToNavigationTo : Int?
    @Published var recievedNotificationFromChatID: String?
}

ContentView 的轻量级示例

struct ContentView: View {
    
    @State var selection: Int = 0
    @EnvironmentObject var session: SessionStore
    
    @State var activeChatID: String?
    
    let tabBarImageNames = ["person.3", "message", "person"]
    
    @EnvironmentObject private var notificationManager: NotificationManager
    

        
    var body: some View {
        
        ZStack {
            Color.black
                .ignoresSafeArea()
            
            VStack {
                
                ZStack {
                    
                    switch selection {
                    case 0:
                         NavigationView {
                            HomeView()
                        }                        
                    case 1:
                        NavigationView {
                            InboxMessagesView(user: session.userSession, activeChatID: $activeChatID)
                            
                        }
                        .accentColor(.white)
                   
                    default:
                        NavigationView {
                            ProfileView(session: session.userSession)
                        }
 
                    }
                    
                }
                
                Spacer()
                
                
                    HStack {
                        
                        ForEach(0..<3) { num in
                            Button {
                                selection = num
                            } label: {
                                Spacer()
                                
                                Image(systemName: tabBarImageNames[num])
                                    .padding(.top, 10)
                                    .font(.system(size: 20, weight: .medium))
                                    .foregroundColor(selection == num ? .red : .white.opacity(0.7))
                                Spacer()
                            }
                            
                        }
                        
                        
                    }
            }
        }
        .ignoresSafeArea(.keyboard, edges: .bottom)
        .onReceive(notificationManager.$pageToNavigationTo) {
            guard let notificationSelection = [=14=] else  { return }
            self.selection = notificationSelection // navigates to page InboxMessagesView
            
        }
        .onReceive(notificationManager.$recievedNotificationFromChatID) {
            guard [=14=] != nil else { return }
            
            self.activeChatID = [=14=] // navigates to the correct chat that is associated with the chatID when the user taps on a chat notification
            
        }

        
    }
    
}

好吧,我在Swift中发现了同样的问题,解决方法是将点击通知的动作延迟一秒。感觉更像是 hack,我想确切地知道异步发生了什么,但它工作得很好。

解决方法如下:

 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { // <- here!!
            self.notificationManager?.pageToNavigationTo = 1
            self.notificationManager?.recievedNotificationFromChatID = chatID
 }