SwiftUI 2 Firebase push notification

人盡茶涼 提交于 2021-01-28 13:30:33

问题


So, I am building iOS app with SwiftUI 2 and new Application life cycle, trying to implement AppsDelegate and Firebase push notification

here my codes sample

import SwiftUI

@main
struct App: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(AppSettings())
        }
    }
}

and AppDelegate

import Firebase
import FirebaseMessaging
import UserNotifications
import Foundation
import UIKit
class AppDelegate: NSObject {
    
    let gcmMessageIDKey = "gcm.message_id"
    
    private func setupFirebase(application: UIApplication) {
        FirebaseApp.configure()

        if #available(iOS 10.0, *) {
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.current().delegate = self

            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
        } else {
            let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }
        Messaging.messaging().delegate = self
        application.registerForRemoteNotifications()
    }
    
}

extension AppDelegate: UIApplicationDelegate {
    
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        setupFirebase(application: application)
        return true
    }
    
}

extension AppDelegate: MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
    }
}

@available(iOS 10, *)
extension AppDelegate: UNUserNotificationCenterDelegate {
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        
        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)
        
        // Print message ID.
        
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }
        
        // Print full message.
        // print(userInfo)
        
        completionHandler([.banner, .badge, .sound])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        // Print message ID.
        
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }
        
        // Print full message.
        print(userInfo)
        
        completionHandler()
    }
    
}

but when I’m testing notifications from firebase console, it's not coming.


回答1:


I was able to get your code to work. I think that Firebase has an issue with swizzling the AppDelegate.

If you disable swizzling by adding the key FirebaseAppDelegateProxyEnabled to your Info.plist, making it a Boolean and setting it to NO.

Then in your AppDelegate you need to add the following, so that it registers the APNS token with Firebase.:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Messaging.messaging().apnsToken = deviceToken
}

For Firebase Cloud Messaging to work it needs to make a link between the APNS token and its token. If no link is made then you will not be able to send messages.

Note that by disabling swizzling there will be certain properties that you will have to update manually.

You should read the documentation carefully. At the time of writing this answer there are several places that you need to update if you disable swizzling.

There are three in the AppDelegate. The first is shown above, the other two are here and are to do with receiving background messages.

You are adding the following line to the delegate methods:

Messaging.messaging().appDidReceiveMessage(userInfo)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented

  // Print message ID.
  if let messageID = userInfo[gcmMessageIDKey] {
    print("Message ID: \(messageID)")
  }

  // Print full message.
  print(userInfo)
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented

  // Print message ID.
  if let messageID = userInfo[gcmMessageIDKey] {
    print("Message ID: \(messageID)")
  }

  // Print full message.
  print(userInfo)

  completionHandler(UIBackgroundFetchResult.newData)
}

There are two in the UNUserNotificationCenterDelegate. Where you add the follow line to the delegate methods

Messaging.messaging().appDidReceiveMessage(userInfo)
extension AppDelegate : UNUserNotificationCenterDelegate {

  func userNotificationCenter(_ center: UNUserNotificationCenter,
                              willPresent notification: UNNotification,
    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    let userInfo = notification.request.content.userInfo

    // With swizzling disabled you must let Messaging know about the message, for Analytics
    Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented

    // Print message ID.
    if let messageID = userInfo[gcmMessageIDKey] {
      print("Message ID: \(messageID)")
    }

    // Print full message.
    print(userInfo)

    // Change this to your preferred presentation option
    completionHandler([[.alert, .sound]])
  }

  func userNotificationCenter(_ center: UNUserNotificationCenter,
                              didReceive response: UNNotificationResponse,
                              withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo
    // Print message ID.
    if let messageID = userInfo[gcmMessageIDKey] {
      print("Message ID: \(messageID)")
    }

    // With swizzling disabled you must let Messaging know about the message, for Analytics
    Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented

    // Print full message.
    print(userInfo)

    completionHandler()
  }
}

This above code is lifted from Firebase's Cloud Messaging documentation. They are very clear in the comments of their code what needs to be done if you have disabled swizzling.

Depending on which other Firebase modules you may include in your project you may have other values you need to update manually. This is where you will need to check carefully with the documentation and code samples to see what changes you have to make.



来源:https://stackoverflow.com/questions/64506267/swiftui-2-firebase-push-notification

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!