Carillon docs

Swift SDK

Install and configure the iOS SDK, forward callbacks, and handle notification taps.

Requirements: iOS 15+ and Swift 5.9+. Configure the SDK with your app's mobile key.

Samples on this page show placeholders. Sign in to the dashboard in this browser and they fill in with your own organization, app and mobile key.

Install

In Xcode, choose File, then Add Package Dependencies, and add:

https://github.com/exostack/carillon-swift

Or in a Package.swift:

.package(url: "https://github.com/exostack/carillon-swift.git", .upToNextMajor(from: "0.2.0"))

Add the Push Notifications capability to your target, which is what puts the aps-environment entitlement in the binary.

Configure

import CarillonCarillon.configure(key: "carillon_mk_live_your_mobile_key", debug: true)// Call when your app should request notification permission.await Carillon.requestPermission()   // .allowed | .denied | .provisional

configure takes an optional endpoint: too, which is how a build points at a different environment.

Forward three callbacks

Forward registration results and notification taps from your app delegate. The SDK does not install these callbacks automatically.

func application(_ app: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken token: Data) {
  Carillon.didRegister(token: token)
}

func application(_ app: UIApplication,
                 didFailToRegisterForRemoteNotificationsWithError error: Error) {
  Carillon.didFailToRegister(error)
}

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completion: @escaping () -> Void) {
  Carillon.didOpen(response)
  completion()
}

Set UNUserNotificationCenter.current().delegate as the first thing in didFinishLaunching, so an app launched by a tap has somewhere to deliver its open to.

Identity, tags, and open callbacks

Carillon.identify("user-42")
Carillon.clearIdentity()

Carillon.setTags(["plan": "pro", "seats": 5, "beta": true])

Carillon.optOut()
Carillon.optIn()

Carillon.onOpened = { notification in
  // notification.deliveryId, notification.userInfo, notification.openedAt
}

let info = Carillon.debugInfo()

setTags replaces the map whole rather than merging, so removing a tag means sending the map without it.

Environment detection

The SDK reads aps-environment from the embedded provisioning profile at runtime.

SigningEnvironment
development profilesandbox
Simulatorsandbox
No profile: TestFlight, App Storeproduction

It is re-derived on every launch and never persisted, so a rebuild with different signing reports the new environment immediately.

Registration is also attempted on the simulator. Actual sandbox token support depends on the host and simulator runtime. If token acquisition fails, inspect didFailToRegister and debugInfo(), or use a physical device.

Foreground notifications

Forward presentation to the SDK, then choose whether to show the banner:

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            willPresent notification: UNNotification,
                            withCompletionHandler completion: @escaping (UNNotificationPresentationOptions) -> Void) {
  Carillon.willPresent(notification, completionHandler: completion)
}

Carillon.onReceived = { notification in
  // Read notification.data and return .suppress for your own in-app UI.
  return .show
}

Carillon.clearNotifications()

Without a handler, the SDK requests banner, list, sound and badge presentation. Notifications without a Carillon stamp have a nil deliveryId. Clearing removes delivered notifications from Notification Center; it does not change subscription or permission.

Images

Add a Notification Service Extension target named CarillonNotificationExtension in Xcode. Use bundle ID <your bundle ID>.CarillonNotificationExtension, and add the Swift package's CarillonNotificationExtension product to this target.

import UserNotifications
import CarillonNotificationExtension

final class NotificationService: UNNotificationServiceExtension {
  private var helper: CarillonNotificationExtension?

  override func didReceive(_ request: UNNotificationRequest,
    withContentHandler handler: @escaping (UNNotificationContent) -> Void) {
    helper = CarillonNotificationExtension.didReceive(request, withContentHandler: handler)
  }

  override func serviceExtensionTimeWillExpire() {
    CarillonNotificationExtension.serviceExtensionTimeWillExpire(helper)
  }
}

The helper reads carillon.image. It downloads over HTTPS within 20 seconds, limits the file to 10 MiB, and keeps the original notification if the download or attachment fails. No App Group is needed. Add the extension bundle ID to your signing profiles, including Fastlane match. Send a notification with payload.image to verify the attachment on a device.

Device ID

Carillon.deviceId is nil before registration succeeds. Carillon.onDeviceIdChanged fires on first registration and when the server returns a different ID. Token rotation preserves the ID when the SDK's stored installation proof matches. See device identity.

Where state lives

UserDefaults in the app container: the last registered state hash, the server device id, installation proof and any queued events. The OS may restore this state from a backup; the device ID is not an authentication credential.

Track opens · Devices · Troubleshooting

On this page