Skip to main content

Receive Push Notifications

  1. Add your iOS app on Firebase Console: Project Overview > Add App > iOS

  2. Download GoogleService-Info.plist

  3. Add GoogleService-Info.plist to the Xcode project (Add Files…, enable Copy items if needed). Select the plist in the Project Navigator, open the File Inspector (right sidebar, first tab), and under Target Membership check only your main application target—the target that produces your runnable app (usually named like your app). That tells Xcode to copy the plist into that app’s bundle so Firebase can load it. Do not check unrelated targets (e.g. tests or extensions) unless you intentionally use Firebase there too.

  4. Add the DashX packages: in Xcode go to FileAdd Package Dependencies…, enter https://github.com/dashxhq/dashx-ios.git, then add both DashX and DashXFirebase to your app target.

    info

    The CocoaPods DashX pod ships the core library only. DashXFirebase (including DashXAppDelegate) is provided via Swift Package Manager from the same repository.

  5. Add Firebase for iOS (for example pod 'FirebaseMessaging' in your Podfile and run pod install, or add the Firebase iOS SDK via Swift Package Manager). Ensure FirebaseApp.configure() runs before you rely on FCM.

  6. Implement DashXAppDelegate

import DashX
import DashXFirebase
import FirebaseCore
import FirebaseMessaging

@main
class AppDelegate: DashXAppDelegate, MessagingDelegate {

// ...

override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
DashX.configure(
withPublicKey: "YOUR_PUBLIC_KEY"
)

// Initialize Firebase and FCM. `FirebaseApp.configure()` must run
// before any Firebase API is touched. Setting the messaging delegate
// lets `messaging(_:didReceiveRegistrationToken:)` below forward the
// FCM token to DashX.
FirebaseApp.configure()
Messaging.messaging().delegate = self

// Request permission for push notifications
DashX.requestNotificationPermission { authorizationStatus in
// .authorized / .denied / .notDetermined / .provisional / .ephemeral
}

// This method registers the device token with DashX
DashX.subscribe()

return true
}

// Forward the FCM token to DashX whenever Firebase issues a new one
// (initial registration, token rotation, etc.). Without this, `subscribe`
// will only have the APNs token and broadcasts routed through FCM won't
// reach the device. `DashXAppDelegate` already forwards the APNs token in
// `didRegisterForRemoteNotificationsWithDeviceToken`.
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
guard let fcmToken else { return }
DashX.setFCMToken(to: fcmToken)
}

// Show banners for pushes that arrive while the app is in foreground.
// Default in DashXAppDelegate is `[]`, which suppresses them silently.
override func notificationDeliveredInForeground(message: [AnyHashable: Any]) -> UNNotificationPresentationOptions {
return [.banner, .list, .sound, .badge]
}

// Intercept tap navigation. Return `true` to handle yourself and skip
// the SDK's default routing. Return `false` (the default) to let the SDK
// apply its built-in behaviour (opens deep links via `handleLink`, rich
// landings in an in-app browser, etc.). See [Deep linking](./deep-linking)
// for the full NavigationAction taxonomy.
override func onNotificationClicked(
message: [AnyHashable: Any],
action: NavigationAction?,
actionIdentifier: String
) -> Bool {
switch actionIdentifier {
case "ACCEPT_ACTION": /* your handling */; return true
case "DECLINE_ACTION": /* your handling */; return true
default: return false
}
}

// Optional: custom deep-link handling. Default (since SDK 1.3.0) opens
// the URL via `UIApplication.shared.open(_:)`. Override to route URLs
// inside the app; call `super.handleLink(url:)` to keep the default
// OS-level open behaviour alongside your own logic.
override func handleLink(url: URL) {
// route `url` to the appropriate in-app screen
}
}
  1. Update Info.plist and entitlements

Add the following to the main app's Info.plist:

<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
  • FirebaseAppDelegateProxyEnabled = NO disables Firebase's AppDelegate swizzling — DashXAppDelegate forwards APNs registration explicitly, and double-forwarding causes duplicate FCM registrations.
  • remote-notification background mode lets iOS wake the app for background/silent orchestration pushes (e.g. trackNotification flows).

Then add the push entitlement to the app's .entitlements file (create one via Signing & Capabilities → + Capability → Push Notifications if you don't already have it):

<key>aps-environment</key>
<string>development</string>

Use production for release builds. Without this entitlement registerForRemoteNotifications silently fails and you will never receive an APNs token.

  1. Configure rich push content

DashX 1.3.0+ delivers pushes as user-visible APNs alert pushes (iOS renders the banner itself). To attach images, register dynamic action buttons, and track delivery when the app isn't running, add a Notification Service Extension target:

  1. In Xcode, File → New → Target… → Notification Service Extension.
  2. Delete the auto-generated NotificationService.swift.
  3. In File → Add Package Dependencies…, add the DashXNotificationServiceExtension library to the new NSE target (or add pod 'DashX/NotificationServiceExtension' inside the NSE target in your Podfile).
  4. Create a new NotificationService.swift inside the NSE target:
import DashXNotificationServiceExtension

final class NotificationService: DashXNotificationService {}
  1. Add the same Info.plist keys to the NSE target that your main app uses for xcconfig-driven configuration (same names, same values). The NSE runs in its own process and cannot read the host app's bundle, so it needs its own copies:
<key>DASHX_BASE_URI</key>
<string>$(DASHX_BASE_URI)</string>
<key>DASHX_PUBLIC_KEY</key>
<string>$(DASHX_PUBLIC_KEY)</string>
<key>DASHX_TARGET_ENVIRONMENT</key>
<string>$(DASHX_TARGET_ENVIRONMENT)</string>

DASHX_TARGET_ENVIRONMENT is optional — include it only if your workspace uses environment-scoped broadcasts.

See iOS SDK → Notification Service Extension for a deeper walkthrough.