'App delegate methods not triggered on receipt of firebase notifications in iOS, but display in banner on screen

I've implemented FCM push notifications for my iOS app such that when a notification is delivered a banner with the expected payload is displayed on my iPhone screen, but none of my App Delegate methods are invoked.

My implementation closely follows the firebase cloud messaging documentation here with method swizzling disabled.

Why don't my app delegate methods trigger when I receive a push notification?

How can I execute code on receipt of a remote notification?

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

    FirebaseApp.configure()
    UNUserNotificationCenter.current().delegate = self
    Messaging.messaging().delegate = self
    return true
  }
}

extension AppDelegate: UNUserNotificationCenterDelegate {
  
  /* Invoked when a notification arrives when the app is running in the foreground. */
  func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    willPresent notification: UNNotification,
    withCompletionHandler completionHandler:
    @escaping (UNNotificationPresentationOptions) -> Void
  ) {
    let userInfo = notification.request.content.userInfo
    Messaging.messaging().appDidReceiveMessage(userInfo)
    completionHandler([[.banner, .sound, .badge]])
  }

  /* Invoked when notification arrives when the app is running in the background. */
  func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    didReceive response: UNNotificationResponse,
    withCompletionHandler completionHandler: @escaping () -> Void
  ) {
    let userInfo = response.notification.request.content.userInfo
    Messaging.messaging().appDidReceiveMessage(userInfo)
    completionHandler()
  }
  
  /** Method swizzling disabled requirement. */
  func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
  ) {
    Messaging.messaging().apnsToken = deviceToken
  }
  
  func application(_ application: UIApplication,
  didReceiveRemoteNotification userInfo: [AnyHashable : Any],
     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    Messaging.messaging().appDidReceiveMessage(userInfo)
    completionHandler(.noData)
  }
}

extension AppDelegate: MessagingDelegate {
  func messaging(
    _ messaging: Messaging,
    didReceiveRegistrationToken fcmToken: String?
  ) {
    let tokenDict = ["token": fcmToken ?? ""]
    NotificationCenter.default.post(
      name: Notification.Name("FCMToken"),
      object: nil,
      userInfo: tokenDict
    )
    writeFCMTokenToFirestore(token: fcmToken)
  }
}

On the backend I am using the firebase admin SDK within a Cloud Function to send notifications with a custom payload, as below.

const admin = require('firebase-admin');

const token = getDeviceToken();

const payload = {
  notification: {
    title: 'test', 
    badge: '1'
  }
}

admin.messaging().sendToDevice(token, payload)
 .then((response) => {
    // Success
 })
 .catch((error) => {
    // Failure
 });


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source