AppDelegate & SceneDelegate Configuration
Pulsate needs a small number of callbacks from your app: push-token registration, background pushes and notification taps. You keep ownership of your UIApplicationDelegate and forward those callbacks to Pulsate.
Integration modes
Section titled “Integration modes”Create the manager with getInstance(withAuthorizationData:withLaunchOptions:andPulsateNotificationDelegate:). Pulsate never replaces your app delegate; the one choice is who owns the UNUserNotificationCenter delegate:
andPulsateNotificationDelegate |
Notification delegate | You forward |
|---|---|---|
false (recommended) |
Your app | Sections 2 and 3 |
true |
Pulsate | Section 2 |
1. Initialize Pulsate
Section titled “1. Initialize Pulsate”Create the manager in application(_:didFinishLaunchingWithOptions:), and make your app delegate the notification center’s delegate before didFinishLaunching returns.
import UIKitimport UserNotificationsimport PULPulsate
@mainclass AppDelegate: UIResponder, UIApplicationDelegate {
var pulsateManager: PULPulsateManager?
/// Pulsate's delegate proxy. Fetched on demand so it is always current. var pulsateSystemManager: (UIApplicationDelegate & UNUserNotificationCenterDelegate)? { PULPulsateFactory.getDefaultInstance()?.getPulsateSystemManager() }
func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Must be set before this method returns. A notification tap that launches the app // is delivered as soon as launch finishes; with no delegate set, it is dropped. UNUserNotificationCenter.current().delegate = self
do { let authData = try PULAuthorizationData(withAppId: "APP_ID", andAppKey: "APP_KEY") pulsateManager = try PULPulsateFactory.getInstance( withAuthorizationData: authData, withLaunchOptions: launchOptions, andPulsateNotificationDelegate: false ) } catch { print("Pulsate init failed: \(error)") } return true }}getPulsateSystemManager() returns Pulsate’s delegate proxy, typed (UIApplicationDelegate & UNUserNotificationCenterDelegate)?. Forward each callback below to it.
2. Forward the push callbacks (UIApplicationDelegate)
Section titled “2. Forward the push callbacks (UIApplicationDelegate)”These stay on your app delegate whether or not your app uses scenes. Without them your push token is never registered with Pulsate.
extension AppDelegate {
func application( _ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data ) { pulsateSystemManager?.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) }
func application( _ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error ) { pulsateSystemManager?.application?(application, didFailToRegisterForRemoteNotificationsWithError: error) }
func application( _ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void ) { pulsateSystemManager?.application?(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler) }}3. Forward notification presentation and taps (UNUserNotificationCenterDelegate)
Section titled “3. Forward notification presentation and taps (UNUserNotificationCenterDelegate)”Skip this section if you passed andPulsateNotificationDelegate: true.
Forward to Pulsate only the pushes Pulsate sent - those whose payload sender is "Pulsate" or "PulsateDebug". Handle every other push yourself: Pulsate does not call the completion handler for pushes it did not send.
extension AppDelegate: UNUserNotificationCenterDelegate {
private func isPulsatePush(_ notification: UNNotification) -> Bool { let sender = notification.request.content.userInfo["sender"] as? String return sender == "Pulsate" || sender == "PulsateDebug" }
func userNotificationCenter( _ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void ) { if isPulsatePush(notification), let pulsate = pulsateSystemManager { pulsate.userNotificationCenter?(center, willPresent: notification, withCompletionHandler: completionHandler) return } // Not a Pulsate push - handle it yourself completionHandler([.banner, .list, .badge, .sound]) }
func userNotificationCenter( _ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void ) { if isPulsatePush(response.notification), let pulsate = pulsateSystemManager { // Pulsate opens the campaign's URL, deeplink, card or feed pulsate.userNotificationCenter?(center, didReceive: response, withCompletionHandler: completionHandler) return } // Not a Pulsate push - handle it yourself completionHandler() }}4. Scene-based apps (UIScene lifecycle)
Section titled “4. Scene-based apps (UIScene lifecycle)”Apps built with Xcode 27 must use the UIScene lifecycle (a UIApplicationSceneManifest in Info.plist). Pulsate’s integration does not change: everything it needs stays on the app delegate, and your scene delegate forwards nothing to Pulsate.
| Callback | Where it goes |
|---|---|
| Push token, registration failure, background push | App delegate (section 2) |
UNUserNotificationCenter delegate |
App delegate, set in didFinishLaunching (section 3) |
| Foreground / background | Nothing to forward - Pulsate handles it |
Migrating to the 4.10 initializer
Section titled “Migrating to the 4.10 initializer”You call getInstance(...withPulsateAppDelegate: false, andPulsateNotificationDelegate: X) - remove the withPulsateAppDelegate: false argument. Nothing else changes.
You call getInstance(withLaunchOptions:), getInstance(withAuthorizationData:withLaunchOptions:), or pass withPulsateAppDelegate: true - Pulsate is currently your app delegate:
- Switch to
getInstance(withAuthorizationData:withLaunchOptions:andPulsateNotificationDelegate:). Passtrueto keep Pulsate as the notification delegate, as before, orfalseand forward as in section 3. - Forward the push callbacks in section 2 - without this, your push token is never registered.
- Nothing else needs forwarding: not the foreground/background callbacks,
application(_:open:options:),application(_:continue:restorationHandler:)orapplicationWillTerminate(_:).

