Get started with Firebase Cloud Messaging in Apple platform apps

Select platform: iOS+ Android Web Flutter Unity C++


This guide describes how to get started with Firebase Cloud Messaging in your Apple platform (like iOS) client apps so that you can reliably send messages.

For Apple client apps, you can receive notification and data payloads up to 4096 bytes over the Firebase Cloud Messaging APNs interface.

To write your client code in Objective-C or Swift, we recommend that you use the FIRMessaging API. The quickstart example provides sample code for both languages.

Before you get started, add Firebase to your Apple project.

Method swizzling in Firebase Cloud Messaging

The FCM SDK performs method swizzling in two key areas: mapping your APNs token to the Firebase Installation ID or FCM registration token and capturing analytics data during downstream message callback handling. Developers who prefer not to use swizzling can disable it by adding the flag FirebaseAppDelegateProxyEnabled in the app's Info.plist file and setting it to the boolean value NO. Relevant areas of the guides provide code examples, both with and without method swizzling enabled.

Upload your APNs authentication key

Upload your APNs authentication key to Firebase. If you don't already have an APNs authentication key, make sure to create one in the Apple Developer Member Center.

  1. In the Firebase console, go to Settings > General. Then, click the Cloud Messaging tab.
  2. In APNs authentication key under iOS app configuration, click Upload to upload your development authentication key, or production authentication key, or both. At least one is required.
  3. Browse to the location where you saved your key, select it, and click Open. Add the key ID for the key (available in the Apple Developer Member Center) and click Upload.

Register for remote notifications

Either at startup, or at the desired point in your application flow, register your app for remote notifications. Call registerForRemoteNotifications as shown:

Swift

UNUserNotificationCenter.current().delegate = self

let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
  options: authOptions,
  completionHandler: { _, _ in }
)

application.registerForRemoteNotifications()

Objective-C

[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
    UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
    requestAuthorizationWithOptions:authOptions
    completionHandler:^(BOOL granted, NSError * _Nullable error) {
      // ...
    }];

[application registerForRemoteNotifications];

Access the Firebase Installation ID

By default, the FCM SDK registers the app instance with FCM and returns a Firebase Installation ID (FID) for the client app instance on app launch. Similar to the APNs device token, this FID allows you to send targeted notifications to any particular instance of your app.

In the same way that Apple platforms typically deliver an APNs device token at app startup, FCM provides an FID for targeting notifications. The FCM SDK delivers the FID using the FIRMessagingDelegate's messaging:didReceiveRegistration: method, automatically monitors for FID changes, and invokes the method with a new FID when a change is detected. We recommend that you retrieve and upload the FID regularly because the FID can rotate after the initial startup.

For details on when FIDs are reissued and how to manually monitor them, see Monitor the Firebase installation ID lifecycle.

Enable registration using Firebase Installation ID

To enable registering your app instance with FCM using Firebase Installation ID (FID), add the following metadata flag to your Info.plist file, not your GoogleService-Info.plist file:

FirebaseMessagingInstallationIdEnabled = YES

Set the messaging delegate

To receive FIDs, implement the messaging delegate protocol and set the delegate property of FIRMessaging after calling [FIRApp configure]. For example, if your application delegate conforms to the messaging delegate protocol, you can set the delegate on application:didFinishLaunchingWithOptions: to itself.

Swift

Messaging.messaging().delegate = self

Objective-C

[FIRMessaging messaging].delegate = self;

Implement the didReceiveRegistration method

App instances are targeted using the FID once registration completes. To receive the FID upon registration, implement the messaging:didReceiveRegistration: method. This method is typically invoked once per app startup with the FID. When this method is called, you can perform the following actions:

  • If you haven't sent the FID to your server, or sent the FID recently, send it to your application server.
  • If the subscription is new or the user re-installed the app, subscribe the FID to topics.

Swift

func messaging(_ messaging: Messaging, didReceiveRegistration installationId: String?) {
  print("Firebase Installation ID: \(String(describing: installationId))")
  // Note: This callback is fired at each app startup.

  if let installationId = installationId {
    // Send the Firebase Installation ID to your app server.
    sendRegistrationToServer(installationId)
  }
}
    

Objective-C

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistration:(nullable NSString *)installationId {
  NSLog(@"Firebase Installation ID: %@", installationId);
  // Note: This callback is fired at each app startup.

  if (installationId != nil) {
    // Send the Firebase Installation ID to your app server.
    [self sendRegistrationToServer:installationId];
  }
}
    

Manually register when auto-initialization is disabled

If you have disabled auto-initialization, the FCM SDK won't automatically register the app instance with FCM at app startup. You must call register on app startup to trigger registration and FID delivery through the messaging:didReceiveRegistration: method:

Swift

// Trigger manual registration if auto-initialization is turned off.
Messaging.messaging().register { error in
    if let error = error {
        // Handle the error
        print("Failed registering: \(error)")
        return
    }
    // Registration was successful. FID is delivered through the messaging:didReceiveRegistration: method.
    print("Successfully registered.")
}
    

Objective-C

// Trigger manual registration if auto-initialization is turned off.
[[FIRMessaging messaging] registerWithCompletion:^(NSError * _Nullable error) {
    if (error) {
        // Handle the error
        NSLog(@"Failed registering: %@", error);
        return;
    }
    // Registration was successful. FID is delivered through the messaging:didReceiveRegistration: method.
    NSLog(@"Successfully registered.");
}];
    

Swizzling disabled: mapping your APNs token and FID

If you've disabled method swizzling or you're building a SwiftUI app, you must explicitly map your APNs token to the Firebase Installation IDs (FID). Implement the application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method to retrieve the APNs token, and then set the apnsToken property of Messaging:

Swift

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

Objective-C

// With "FirebaseAppDelegateProxyEnabled": NO
- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [FIRMessaging messaging].APNSToken = deviceToken;
}

Once the FID is registered, you can access it and listen for refresh events using the same methods as when swizzling is enabled.

Access the registration token

By default, the FCM SDK generates a registration token for the client app instance on app launch. Similar to the APNs device token, this token allows you to send targeted notifications to any particular instance of your app.

In the same way that Apple platforms typically deliver an APNs device token on app start, FCM provides a registration token via FIRMessagingDelegate's messaging:didReceiveRegistrationToken: method. The FCM SDK retrieves a new or existing token during initial app launch and whenever the token is updated or invalidated. In all cases, the FCM SDK calls messaging:didReceiveRegistrationToken: with a valid token.

The registration token may change when:

  • The app is restored on a new device
  • The user uninstalls/reinstall the app
  • The user clears app data.

Set the messaging delegate

To receive registration tokens, implement the messaging delegate protocol and set FIRMessaging's delegate property after calling [FIRApp configure]. For example, if your application delegate conforms to the messaging delegate protocol, you can set the delegate on application:didFinishLaunchingWithOptions: to itself.

Swift

Messaging.messaging().delegate = self

Objective-C

[FIRMessaging messaging].delegate = self;

Fetching the current registration token

Registration tokens are delivered via the method messaging:didReceiveRegistrationToken:. This method is called generally once per app start with registration token. When this method is called, it is the ideal time to:

  • If the registration token is new, send it to your application server.
  • Subscribe the registration token to topics. This is required only for new subscriptions or for situations where the user has re-installed the app.

You can retrieve the token directly using token(completion:). A non null error is provided if the token retrieval failed in any way.

Swift

Messaging.messaging().token { token, error in
  if let error = error {
    print("Error fetching remote FCM registration token: \(error)")
  } else if let token = token {
    print("Remote instance ID token: \(token)")
  }
}

Objective-C

[[FIRMessaging messaging] tokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) {
  if (error != nil) {
    NSLog(@"Error fetching the remote FCM registration token: %@", error);
  } else {
    NSLog(@"Remote FCM registration token: %@", token);
    NSString* message =
      [NSString stringWithFormat:@"FCM registration token: %@", token];
    // display message
    NSLog(@"%@", message);
  }
}];

You can use this method at any time to access the token instead of storing it.

Monitor token refresh

To be notified whenever the token is updated, supply a delegate conforming to the messaging delegate protocol. The following example registers the delegate and adds the proper delegate method:

Swift

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
  print("Firebase registration token: \(String(describing: fcmToken))")
  // TODO: If necessary send token to application server.
  // Note: This callback is fired at each app startup and whenever a new token is generated.
}

Objective-C

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    NSLog(@"FCM registration token: %@", fcmToken);
    // Notify about received token.
    NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
    [[NSNotificationCenter defaultCenter] postNotificationName:
     @"FCMToken" object:nil userInfo:dataDict];
    // TODO: If necessary send token to application server.
    // Note: This callback is fired at each app startup and whenever a new token is generated.
}

Alternatively, you can listen for an NSNotification named kFIRMessagingRegistrationTokenRefreshNotification rather than supplying a delegate method. The token property always has the current token value.

Swizzling disabled: mapping your APNs token and registration token

If you have disabled method swizzling, or you are building a SwiftUI app, you'll need to explicitly map your APNs token to the FCM registration token. Implement the application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method to retrieve the APNs token, and then set Messaging's apnsToken property:

Swift

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

Objective-C

// With "FirebaseAppDelegateProxyEnabled": NO
- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [FIRMessaging messaging].APNSToken = deviceToken;
}

After the FCM registration token is generated, you can access it and listen for refresh events using the same methods as with swizzling enabled.

Prevent auto initialization

When a FCM registration is generated, the library uploads the identifier and configuration data to Firebase. If you want to get an explicit opt-in from users first, you can prevent auto registration at configure time by disabling FCM. To do this, add a metadata value to your Info.plist (not your GoogleService-Info.plist):

FirebaseMessagingAutoInitEnabled = NO

To re-enable FCM, you can make a runtime call:

Swift

Messaging.messaging().autoInitEnabled = true

Objective-C

[FIRMessaging messaging].autoInitEnabled = YES;

This value persists across app restarts once set.

Set up the notification service extension

To send notifications that include images to Apple devices, you must add a notification service extension. This extension allows devices to display images delivered in the notification payload. If you don't plan to send images in notifications, you can skip this step.

To add a service extension, perform the required setup tasks for modifying and presenting notifications in APNs, and then add the FCM extension helper API in NotificationService.m. Specifically, instead of completing the callback with self.contentHandler(self.bestAttemptContent);, complete it with FIRMessaging extensionHelper as shown:

@interface NotificationService () <NSURLSessionDelegate>
@property(nonatomic) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property(nonatomic) UNMutableNotificationContent *bestAttemptContent;
@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];

    // Modify the notification content here as you want
self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]",
self.bestAttemptContent.title];

  // Call FIRMessaging extension helper API.
  [[FIRMessaging extensionHelper] populateNotificationContent:self.bestAttemptContent
withContentHandler:contentHandler];

}
...

Send a notification message

  1. Install and run the app on the target device. On Apple devices, accept the request for permission to receive remote notifications.

  2. Check that the app is in the background on the device.

  3. In the Firebase console, go to DevOps & Engagement > Messaging

  4. Create a campaign.

    • If this is your first message:

      1. Select Create your first campaign.

      2. Select Firebase Notification messages and select Create.

    • If you have previously created campaigns:

      1. On the Campaigns tab, select New campaign.

      2. Click Notifications.

  5. Enter the message text.

  6. Select Send test message from the right pane.

  7. In the field labeled Add a Firebase Installation ID or FCM registration token, enter your registration token.

  8. Select Test.

After you select Test, the targeted client device, with the app in the background, should receive the notification.

For insight into message delivery to your app, go to the DevOps & Engagement > Messaging > Reports dashboard in the Firebase console. This dashboard records the number of messages sent and opened on Apple and Android devices, along with data for "impressions" (notifications seen by users) for Android apps.

Next steps

After you have completed the setup steps, here are a few options for moving forward with FCM for Apple platforms: