Swift
Native Swift SDK.
Overview
The Swift SDK provides client-side feature flag evaluation, identity lifecycle APIs, telemetry batching, stream updates with polling fallback, and state subscriptions.
Get started
Install with SwiftPM
dependencies: [ .package(url: "https://github.com/Truflag/truflag-swift-sdk.git", from: "0.2.2")]Install with CocoaPods
pod 'TruflagSDK', '~> 0.2'Configure
apiKey is required. If no user is supplied, the client starts with an anonymous identity. configure() awaits the initial refresh before returning.
import TruflagSDK let client = TruflagClient() try await client.configure( TruflagConfigureOptions( apiKey: "env_c_...", user: TruflagUser( id: "user-123", attributes: [ "plan": AnyCodable("pro"), "country": AnyCodable("US"), ] ) )) // configure() awaits initial refresh before returninglet ready = await client.isReady()Configuration options
TruflagConfigureOptions( apiKey: "env_c_...", user: TruflagUser(id: "user-123"), baseURL: URL(string: "https://sdk.truflag.com")!, streamURL: URL(string: "wss://stream.sdk.truflag.com")!, streamEnabled: true, pollingIntervalMs: 60_000, requestTimeoutMs: 6_000, cacheTtlMs: 300_000, telemetryFlushIntervalMs: 10_000, telemetryBatchSize: 50, telemetryEnabled: true, debugLoggingEnabled: false)Identity
try await client.login( user: TruflagUser( id: "user-456", attributes: ["plan": AnyCodable("enterprise")] )) try await client.setAttributes([ "region": AnyCodable("us-east-1"), "cohort": AnyCodable("A"),]) try await client.logout() // switches to anonymous identity and refreshesFlags and exposure
getFlag() and getAllFlags() automatically enqueue exposure events for returned flags. getFlagPayload() does not emit exposure by itself.
let enabled: Bool = await client.getFlag("new-checkout", defaultValue: false)let variant: String = await client.getFlag("checkout-variant", defaultValue: "control") let payload = await client.getFlagPayload("new-checkout")let allFlags = await client.getAllFlags() // Optional manual exposure signal for state-driven reads:await client.notifyFlagRead(flagKey: "new-checkout")Events
Use track() for custom events. Set immediate: true to flush now.
try await client.track( eventName: "checkout_completed", properties: [ "source": AnyCodable("swift"), "value": AnyCodable(99.95), ], immediate: true // flush now instead of waiting for batch/timer) try await client.expose(flagKey: "new-checkout")Reactive updates
Subscribe to global state, per-flag updates, or consume async streams.
let token = await client.subscribe { Task { let state = await client.getState() print("ready:", state.ready, "flags:", state.flags.count) }} let flagToken = await client.subscribeFlag("new-checkout") { flag in print("flag changed:", flag?.value.value ?? "nil")} // Async stream alternatives:let stateStream = await client.stateStream()let flagStream = await client.flagStream("new-checkout") // Later:await client.unsubscribe(token)await client.unsubscribeFlag(flagToken)Troubleshooting
Flags return fallback values
Confirm await client.isReady() is true, yourapiKey targets the expected environment, and the flag key exists.
Stream updates are not arriving
Verify streamEnabled and streamURL. Polling fallback remains available.