繁体   English   中英

Swift & FCM:从后台切换到前台时如何获取推送通知数据?

[英]Swift & FCM : How to get push notification data when switching from Background to Foreground?

我正在 Swift 中配置推送通知。 到目前为止,我有 3 个场景。

1 - App In Foreground 在前台,我认为我做的一切都是正确的,因为我确实收到了推送通知数据。

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        print("userNotificationCenter willPresent")
        let content = notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        UIApplication.shared.applicationIconBadgeNumber = 0
        UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
        
        completionHandler([.alert, .sound])
        
    }

2 - 用户点击推送通知横幅 这也工作正常。

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        print("userNotificationCenter didReceive")
       defer {
           completionHandler()
       }
       guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else {
           return
       }
        
        let content = response.notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        
        UNUserNotificationCenter.current().removeAllDeliveredNotifications()
    }

3 - 应用在后台,然后用户进入应用在这种情况下,推送通知到达用户的手机。 但是,他们不是点击推送通知本身,而是进入应用程序。 我无法从推送通知中获取任何信息

任何人都可以帮助如何配置第三个场景? 谢谢你。

完整代码

import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        FirebaseApp.configure()
        //        application.registerForRemoteNotifications()
        setupNotification(on: application)
        //        UIApplication.shared.applicationIconBadgeNumber = 0
        
        return true
    }
    
    // MARK: UISceneSession Lifecycle
    
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }
    
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("Received data message: \(userInfo)")
        
        let name = Notification.Name(rawValue: K.Event.pushRequest)
        NotificationCenter.default.post(name: name, object: nil)
        
        completionHandler(.newData)
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("deviceToken : \(deviceToken)")
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Error : \(error.localizedDescription)")
    }
    
}

//MARK: - UNUserNotificationCenterDelegate
// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
    
    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        print("userNotificationCenter willPresent")
        let content = notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        UIApplication.shared.applicationIconBadgeNumber = 0
        UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
        
        completionHandler([.alert, .sound])
        
    }
    
    // When user click on push notification
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        print("userNotificationCenter didReceive")
       defer {
           completionHandler()
       }
       guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else {
           return
       }
        
        let content = response.notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        
        UNUserNotificationCenter.current().removeAllDeliveredNotifications()
    }
    
}

//MARK: - MessagingDelegate
extension AppDelegate : MessagingDelegate {
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("Firebase registration token: \(String(describing: fcmToken))")
        
        let dataDict:[String: String] = ["token": fcmToken ?? ""]
        
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        
    }
    // [END refresh_token]
}

extension AppDelegate {
    func setupNotification(on application: UIApplication) {
        let notificationCenter = UNUserNotificationCenter.current()
        notificationCenter.delegate = self
        Messaging.messaging().delegate = self
        notificationCenter.requestAuthorization(options: [.alert, .sound]) { granted, error in
            if let error = error {
                print("Failed to requestion authorization for notification center:  \(error.localizedDescription)")
                return
            }
            
            guard granted else {
                print("Failed to requestion authorization for notification center: not granted")
                return
            }
            
            DispatchQueue.main.async {
                application.registerForRemoteNotifications()
            }
            
        }
//        application.registerForRemoteNotifications()
    }
}

你需要考虑applicationState

UIApplication.State

//AppDelegate
func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
    switch UIApplication.shared.applicationState {
    case .active:
        print("Received push message from APNs on Foreground")
    case .background:
        print("Received push message from APNs on Background")
    case .inactive:
        print("Received push message from APNs back to Foreground")
    }
}

当应用从后台到前台时, UIApplication.State inactive

inactive 是 '应用程序在前台运行但未接收事件。 '

因此,我认为执行您想要的行为的最佳方法是自己编写。

例如,

//AppDelegate
func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
    switch UIApplication.shared.applicationState {
    case .active:
        print("Received push message from APNs on Foreground")
    case .background:
        print("Received push message from APNs on Background")
    case .inactive:
        print("Received push message from APNs back to Foreground")

        guard let nav = window?.rootViewController as? UINavigationController,
              let currentVC = nav.viewControllers.last else {return}

        if currentVC is 'youWantViewController' { //if you want ViewController, use notification post
            let name = Notification.Name(rawValue: K.Event.pushRequest)
            NotificationCenter.default.post(name: name, object: nil)
        } else { //move to you want ViewController
           let vc = 'yourViewController'()
           root.navigationController?.pushViewController(vc, animated: true)
        }
    }

    completionHandler(.newData)
}

我希望它会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM