Swift Concurrency & Swift 6 Readiness
This page answers the three questions teams ask when evaluating whether the Zeta iOS SDK is compatible with their own Swift toolchain and concurrency posture.
This guide is for iOS developers who want to understand how the Zeta SDK behaves under Swift 6 strict concurrency, what Sendable annotations apply, and whether their app needs any changes.
- What Swift language version must my app use to consume the SDK?
- What
Sendable/ actor annotations do I need to satisfy on my own types that cross the SDK boundary? - If I turn on Swift 6 strict concurrency mode in my app, does the SDK still build?
On this page
- Minimum Swift toolchain
- What your app must do
- Behavior under Swift 6 strict concurrency
- Sendable expectations
- Notes on async APIs
- Background & rationale
Minimum Swift toolchain
| Surface | Minimum | Notes |
|---|---|---|
swift-tools-version (SPM manifest) | 5.10 | Required to resolve the SDK's SPM package. |
| Xcode | 15.3 | Required for SPM resolution. XCFramework distribution works on earlier Xcode versions. |
| Swift language mode in your app | 5.x (any supported version) | Swift 6 language mode is also supported. See the next section. |
The SDK ships a second, version-specific manifest ([email protected]) so that:
- On Xcode 15.3+ toolchains, SwiftPM uses
Package.swift(Swift 5.10 baseline). - On Xcode 26+ toolchains, SwiftPM uses
[email protected], whereZetaCorestays in Swift 5 language mode with upcoming-feature warnings andZetaNotificationServiceis fully in Swift 6 language mode.
This means your app's choice of Swift language mode is independent of ours — you can build an app in Swift 6 language mode and still consume the SDK.
What your app must do
For the vast majority of consumers: nothing.
- The SDK does not require your app to be in Swift 6 language mode.
- The SDK does not require any
@MainActor,nonisolated, or@unchecked Sendableannotations on your own types. - No SDK API asks you to pass a
Sendableclosure from a non-isolated context; callbacks the SDK delivers to your code are dispatched on behalf of the SDK.
Behavior under Swift 6 strict concurrency
If you enable Swift 6 strict concurrency mode in your app (either via Swift 6 language mode or via SWIFT_STRICT_CONCURRENCY = complete), the SDK continues to build and link cleanly.
ZetaCoreships as a pre-built module; its internal concurrency warnings do not leak into your build.ZetaNotificationServiceis built in Swift 6 language mode against the same toolchain you use.- Public types exposed across the SDK boundary are designed to behave predictably in a strict-concurrency world. See Sendable expectations.
Sendable expectations
Public SDK types you hold on to follow these rules:
| Pattern | Sendable contract |
|---|---|
Value types (enums, structs without reference-type storage) exposed by the SDK | Safe to share across isolation domains. |
Reference-type value models (e.g., ZTAppInboxMessage, ZTCtaAction, ZTUser) | Treat as data snapshots. Do not mutate them after reading; pass copies if you need to cross an isolation boundary. |
Delegates (ZTDeeplinkDelegate, ZTInAppMessageDelegate) | The SDK calls your delegate on the main actor unless otherwise documented on the specific callback. |
Reference-type value models should be treated as effectively immutable after the SDK hands them to you. Additional Sendable conformances will be added in future releases.
Notes on async APIs
- App Inbox uses
async throwsmethods onZTAppInboxManagable. These methods are safe to call from any isolation context; pass the result back to your UI using your preferred isolation strategy. - All other feature areas today expose completion-handler or delegate-based APIs. Where Swift-only
async/throwsaffordances exist, the page for that feature calls them out explicitly.
Background & rationale
The SDK is migrated toward Swift 6 target-by-target rather than all at once. The design choice behind the dual-manifest setup is:
ZetaNotificationService— small, self-contained, no Obj-C interop. It is fully in Swift 6 language mode in[email protected].ZetaCore— large, Obj-C-interoperable surface. It runs in Swift 5 language mode with upcoming-feature flags enabled as warnings (StrictConcurrency,ExistentialAny,InferSendableFromCaptures,DisableOutwardActorInference, and others). A future release will switch to Swift 6 language mode.
For consumers this has two practical effects:
- Backward compatibility is free. If you are on Xcode 15.3+ you see the same SDK you always have.
- Forward compatibility is live. If you are on Xcode 26+ in Swift 6 language mode, the SDK already carries the strict-concurrency and
Sendablework we've done to date, and the remaining warnings are internal to the SDK — they don't reach your build.
See also
- Apple — Migrating to Swift 6
- Apple —
Sendable - Advanced / Logging
