In my SwiftUI app(Xcode 15.0.1, Test iPhone OS: 16.7), Push notification from Firebase is not working when used a separate class for managing MessagingDelegate, UNUserNotificationCenterDelegate but it works when I put everything inside the AppDelegate class.
My AppDelegate looks like this:
class AppDelegate: NSObject, UIApplicationDelegate {
let remoteNotificationManager = RemoteNotificationManager()
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
application.registerForRemoteNotifications()
configureFirebase()
remoteNotificationManager.configure()
return true
}
}
My RemoteNotificationManager class looks like this:
final class RemoteNotificationManager: NSObject {
func configure() {
Messaging.messaging().delegate = self
UNUserNotificationCenter.current().delegate = self
}
}
// MARK: - Firebase MessagingDelegate
extension RemoteNotificationManager: MessagingDelegate {
// This fcmToken will be used for device specific notification from Firebase
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
// TODO: Remove print in integration
if let fcmToken = fcmToken {
print("RemoteNotificationManager fcm from api: \(fcmToken)")
}
}
}
// MARK: - UNUserNotificationCenterDelegate
extension RemoteNotificationManager: UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
NSLog("Failed to register remote notification. %@", error.localizedDescription)
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Messaging.messaging().apnsToken = deviceToken
}
// This method is called when user taps on a notification
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
// TODO: Remove print, integrate
print("RemoteNotificationManager didReceive: \(userInfo)")
completionHandler()
}
// This method is called when user already in the app and notification arrived
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
// TODO: Remove print, integrate completionHandler
print("RemoteNotificationManager willPresent: \(notification.request.content.userInfo)")
completionHandler(.banner)
}
}
In this code above doesn’t receive deviceToken and Messaging.messaging().apnsToken remains nil always. But if I removed the class RemoteNotificationManager, and put all the codes inside AppDelegate like below it works:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
application.registerForRemoteNotifications()
configureFirebase()
configureRemoteNotification()
return true
}
}
extension AppDelegate {
private func configureFirebase() {
FirebaseApp.configure()
}
private func configureRemoteNotification() {
Messaging.messaging().delegate = self
UNUserNotificationCenter.current().delegate = self
}
}
// MARK: - UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
NSLog("Failed to register remote notification. %@", error.localizedDescription)
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Messaging.messaging().apnsToken = deviceToken
}
// This method is called when user taps on a notification
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
// TODO: Remove print, integrate
print("RemoteNotificationManager didReceive: \(userInfo)")
completionHandler()
}
// This method is called when user already in the app and notification arrived
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
// TODO: Remove print, integrate completionHandler
print("RemoteNotificationManager willPresent: \(notification.request.content.userInfo)")
completionHandler(.banner)
}
}
// MARK: - Firebase MessagingDelegate
extension AppDelegate: MessagingDelegate {
// This fcmToken will be used for device specific notification from Firebase
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
// TODO: Remove print in integration
print("APNS TOKEN \(Messaging.messaging().apnsToken)")
if let fcmToken = fcmToken {
print("RemoteNotificationManager fcm from api token: \(fcmToken)")
}
}
}
My question is what’s wrong with having a separate class like RemoteNotificationManager?




