Swift SDK
Install and configure the iOS SDK, forward callbacks, and handle notification taps.
For text, number, boolean and date attributes, SDK methods and audience operators, see Tags.
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-swiftSelect the latest tagged release with the Up to Next Major Version rule. See the published versions.
Or in a Package.swift:
.package(url: "https://github.com/exostack/carillon-swift.git", .upToNextMajor(from: "0.5.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.setTag("plan", "pro")
Carillon.setTagNumber("seats", 5)
Carillon.setTagBoolean("beta", true)
Carillon.optOut()
Carillon.optIn()
Carillon.onOpened = { notification in
// notification.deliveryId, notification.userInfo, notification.openedAt
}
let info = Carillon.debugInfo()setTags merges keys; pass nil to remove a key. setTag("plan", "pro") changes one
key and removeTag("plan") removes it. Omitted keys remain unchanged. See tags.
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.
Related pages
Track opens · Devices · Troubleshooting
Receipt tracking
To record notifications before the app launches, install the notification service
extension above and enable the same App Group on both app and extension targets.
Add CarillonAppGroup to both Info.plist files with the shared group identifier
(for example group.com.example.app.carillon). Include it in both provisioning
profiles and rebuild the app. The extension saves receipts locally; the host app
reports them on its next launch or activation.
SDK 0.5.0 reports observed receipts from its receive callback and recovers notifications still present when the app starts or resumes. It does not report an open for these notifications. See receipt tracking for platform limits, offline reporting, and reading the timestamps in a trace.