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-swiftOr 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 | .provisionalconfigure 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.
| Signing | Environment |
|---|---|
development profile | sandbox |
| Simulator | sandbox |
| No profile: TestFlight, App Store | production |
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.