SwiftUI 2 Firebase 推送通知

标签 swift firebase push-notification swiftui

因此,我正在使用 SwiftUI 2 和新的应用程序生命周期构建 iOS 应用程序,尝试实现 AppsDelegate 和 Firebase 推送通知
这是我的代码示例

import SwiftUI

@main
struct App: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(AppSettings())
        }
    }
}
和 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()
    }
    
}
但是当我测试来自 firebase 控制台的通知时,它并没有到来。

最佳答案

我能够让你的代码工作。我认为 Firebase 在调整 AppDelegate 时存在问题.
如果您通过添加键 FirebaseAppDelegateProxyEnabled 来禁用 swizzling给您的Info.plist ,使其成为 Boolean并将其设置为 NO .
然后在你的AppDelegate您需要添加以下内容,以便它向 Firebase 注册 APNS token 。:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Messaging.messaging().apnsToken = deviceToken
}
要使 Firebase 云消息传递工作,它需要在 APNS token 与其 token 之间建立链接。如果没有链接,那么您将无法发送消息。
请注意,通过禁用 swizzling,将会有某些属性
您将不得不手动更新。

您应该阅读 documentation小心。在撰写此答案时,有 几个地方如果禁用 swizzling,则需要更新。
在 AppDelegate 中。第一个如上所示,另外两个在这里,用于接收后台消息。
您将以下行添加到委托(delegate)方法中:
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)
}
两个 在 UNUserNotificationCenterDelegate 中。将以下行添加到委托(delegate)方法的位置
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()
  }
}
上述代码取自 Firebase 的云消息传递文档。他们在代码注释中非常清楚,如果您禁用了 swizzling,需要做什么。
根据您在项目中可能包含的其他 Firebase 模块,您可能需要手动更新其他值。这是您需要仔细检查文档和代码示例的地方,以了解您必须进行哪些更改。

关于SwiftUI 2 Firebase 推送通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64506267/

相关文章:

java - Firebase - 按值检索数据到外部变量

firebase - 在Firestore中创建空文档

http - Websocket、Server Sent Events (SSE) 和 HTTP2 的 Server Pushing 有什么区别?

java - Android 在注册推送通知期间崩溃

ios - Swift:类型必须实现协议(protocol)并且是给定类的子类

ios - Swift:放置在 tableviewcell 中的图像不可见

ios - 如何使选项卡栏自定义动画仅发生在某个 View Controller 上?

javascript - "ERROR db._checkNotDeleted is not a function"尝试更新我的数据库时

ios - 为什么 cornerRadius 给我一个菱形?

ios - 有没有一种方法可以暂停一个实例的重复通知?