FCM with iOS
Set up Firebase Cloud Messaging for push notifications in your iOS app using Swift.
Prerequisites
- Xcode 16.2+
- An Apple Developer account (paid — required for APNs)
- A physical iOS device (push notifications don't work on simulators)
Setup
1. Add Firebase SDK
In Xcode, navigate to File → Add Package Dependencies… and enter:
https://github.com/firebase/firebase-ios-sdk
Select FirebaseMessaging and click Add Package.
2. Download GoogleService-Info.plist
- Go to Firebase Console → select your project
- Click ⚙️ gear icon → Project settings → General tab
- Under "Your apps," select your iOS app and click Download GoogleService-Info.plist
- Drag the file into the root of your Xcode project and make sure "Add to targets" is checked
3. Configure APNs in Firebase
- Go to Project settings → Cloud Messaging tab
- Under "Apple app configuration," click Upload next to APNs authentication key
- Upload your
.p8key file, then enter your Key ID and Team ID
4. Enable Push Notifications in Xcode
- Select your project target
- Go to Signing & Capabilities
- Click + Capability and add Push Notifications
- Also add Background Modes and check Remote notifications
5. Initialize Firebase
UIKit (AppDelegate)
swiftimport UIKit import FirebaseCore import FirebaseMessaging @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() Messaging.messaging().delegate = self UNUserNotificationCenter.current().delegate = self UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in guard granted else { return } DispatchQueue.main.async { application.registerForRemoteNotifications() } } return true } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken } }
SwiftUI
If you're using SwiftUI, create an AppDelegate class and attach it using @UIApplicationDelegateAdaptor:
swiftimport SwiftUI import FirebaseCore import FirebaseMessaging @main struct YourApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { ContentView() } } } class AppDelegate: NSObject, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { FirebaseApp.configure() Messaging.messaging().delegate = self UNUserNotificationCenter.current().delegate = self UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in guard granted else { return } DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } return true } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken } }
6. Get FCM Token
swiftextension AppDelegate: MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { print("FCM Token: \(fcmToken ?? "")") // Send to your server } }
7. Handle Notifications
swiftextension AppDelegate: UNUserNotificationCenterDelegate { // Foreground notification func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions { let userInfo = notification.request.content.userInfo print("Foreground notification: \(userInfo)") return [[.banner, .badge, .sound]] } // Notification tapped func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { let userInfo = response.notification.request.content.userInfo print("Notification tapped: \(userInfo)") } }
Silent Notifications
Silent (data-only) notifications wake your app in the background:
swiftfunc application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async -> UIBackgroundFetchResult { print("Silent notification: \(userInfo)") return .newData }
To send a silent notification via the FCM HTTP v1 API, set content-available: 1 inside the APNs payload:
json{ "message": { "token": "DEVICE_TOKEN", "apns": { "payload": { "aps": { "content-available": 1 } } } } }
Make sure Background Modes → Remote notifications is enabled in Xcode, or the silent notification won't wake your app.
Testing
-
Run the app on a physical device and copy the FCM token from the Xcode console
-
Open the FCM Tester
-
Paste your service account JSON and the device token
-
Send a test notification
Common Issues
| Issue | Fix |
|---|---|
| No token received | Check APNs key is uploaded in Firebase Console → Cloud Messaging tab |
| Notifications not showing on simulator | Push notifications require a physical device |
| Permission denied | User denied notification permission — consider showing a custom pre-prompt before calling requestAuthorization |
| Badge not updating | Set the badge count in the APNs payload (aps.badge) |
| Silent notification not firing | Enable Background Modes → Remote notifications in Xcode capabilities |
| SwiftUI app not receiving notifications | Use @UIApplicationDelegateAdaptor to connect your AppDelegate |
Related
Was this page helpful?