Up until a year or something, push notifications worked and I've stopped paying attention to them, so I don't know if I'm getting the error since swift/swiftui/xcode/ios update or what ever. This is the error:
APNS device token not set before retrieving FCM Token for Sender ID 'xxxxxxxxxxx'.Be sure to re-retrieve the FCM token once the APNS device token is set.
What I've tried:
Based on all kind of answers for same question.
Revoking the APN token and replacing the old one in firebase project settings
Updating to latest Firebase SDK
Following different tutorials of this implementation, including trying out different AppDelegate
classes from those
Setting FirebaseAppDelegateProxyEnabled
to false
According to a comment here: https://github.com/firebase/firebase-ios-sdk/issues/12445 the reason for that is bad timing in which the functions are called but I don't really understand what exactly he means. The code snipped he provides is something what I'm using anyway many seconds after the app started and the token
is nil
This is the latest AppDeligate that I'm trying out:
class AppDelegate: NSObject, UIApplicationDelegate {
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
}
application.registerForRemoteNotifications()
Messaging.messaging().delegate = self
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
guard let aps = userInfo["aps"] as? [String: AnyObject] else {
completionHandler(.failed)
return
}
print("got something, aka the \(aps)")
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
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 full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([[.banner, .badge, .sound]])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
print(userInfo)
completionHandler()
}
}
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
)
}
}
I hope someone has an idea what's wrong.
The solution was to use it on appear, like so:
@main
struct ExampleApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
.onAppear(perform: {
appDelegate.app = self
})
}
}
}
And inside AppDeligate it should start like this:
class AppDelegate: NSObject, UIApplicationDelegate {
var app: ExampleApp?