iOS SDK
Use Toggly's native iOS SDK in Swift applications for iOS, macOS, tvOS, and watchOS.
Grab the printable Swift / iOS cheat sheet (download PDF) — SwiftUI property wrappers, UIKit, Combine, signed defs.
Overview
The iOS SDK is a modular feature flags solution built entirely in Swift with async/await support. It provides SwiftUI property wrappers, UIKit extensions, and Combine publishers for seamless integration.
Packages
| Package | Description |
|---|---|
TogglyCore | Core functionality, storage, and API client (required) |
TogglySwiftUI | SwiftUI property wrappers, view modifiers, and views |
TogglyUIKit | UIKit extensions and view controller support |
TogglyCombine | Combine publishers for reactive patterns |
Requirements
- iOS 14.0+ / macOS 11.0+ / tvOS 14.0+ / watchOS 7.0+
- Swift 5.5+
- Xcode 15.0+
Installation
Swift Package Manager
Add the package to your Package.swift:
dependencies: [
.package(url: "https://github.com/ops-ai/Toggly.FeatureManagement.git", from: "1.0.0")
]
Then add the products you need:
.target(
name: "YourApp",
dependencies: [
.product(name: "TogglyCore", package: "Toggly.FeatureManagement"),
.product(name: "TogglySwiftUI", package: "Toggly.FeatureManagement"),
// or TogglyUIKit, TogglyCombine
]
)
Xcode
- File → Add Package Dependencies
- Enter:
https://github.com/ops-ai/Toggly.FeatureManagement.git - Select the packages you need (TogglyCore is always required)
Quick Start
Initialize the SDK
import TogglyCore
@main
struct MyApp: App {
init() {
// Configure with your Toggly app key
Toggly.configure(config: TogglyConfig(
appKey: "your-app-key",
environment: "Production"
))
// Initialize asynchronously
Task {
await Toggly.shared.initialize()
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
SwiftUI Usage
import TogglySwiftUI
struct ContentView: View {
// Use the @FeatureFlag property wrapper
@FeatureFlag("new-dashboard") var isNewDashboardEnabled
var body: some View {
VStack {
if isNewDashboardEnabled {
NewDashboardView()
} else {
LegacyDashboardView()
}
// Or use the view modifier
Text("Beta Feature")
.featureFlag("beta-feature")
// Or use FeatureView for cleaner conditional rendering
FeatureView("welcome-banner") {
WelcomeBanner()
}
}
}
}
UIKit Usage
import TogglyUIKit
class MyViewController: FeatureFlagViewController {
override func viewDidLoad() {
super.viewDidLoad()
observeFeature("new-dashboard")
}
override func featureFlagDidChange(_ key: String, isEnabled: Bool) {
// Update UI based on feature flag changes
newDashboardView.isHidden = !isEnabled
}
}
Combine Usage
import TogglyCombine
class ViewModel: ObservableObject {
@Published var isFeatureEnabled = false
private var cancellables = Set<AnyCancellable>()
init() {
TogglyPublishers.featureFlag("new-dashboard")
.receive(on: DispatchQueue.main)
.assign(to: &$isFeatureEnabled)
}
}
Async/Await Usage
import TogglyCore
// Simple feature check
let isEnabled = await Toggly.shared.isFeatureOn("my-feature")
// Feature gate with multiple features
let allEnabled = await Toggly.shared.evaluateFeatureGate(
featureKeys: ["feature-a", "feature-b"],
requirement: .all
)
Configuration Options
TogglyConfig(
appKey: "your-app-key", // Your Toggly.io app key
environment: "Production", // Environment name
baseURI: "https://definitions.toggly.io", // API endpoint (optional)
identity: "user-123", // User ID for targeting (optional)
featureDefaults: [ // Default values (optional)
"feature-a": true,
"feature-b": false
],
showFeatureDuringEvaluation: false, // Show content while loading
refreshInterval: 180, // Auto-refresh interval (seconds)
useSignedDefinitions: false, // Use signed definitions
storage: UserDefaultsStorage() // Custom storage (optional)
)
Offline Support
The SDK automatically caches feature flags for offline use:
// Use UserDefaults for persistent storage
let config = TogglyConfig(
appKey: "your-app-key",
environment: "Production",
storage: UserDefaultsStorage()
)
Local-Only Mode
Use the SDK without connecting to Toggly.io:
let config = TogglyConfig(
featureDefaults: [
"new-dashboard": true,
"beta-feature": false
]
)
Toggly.configure(config: config)
await Toggly.shared.initialize()
Entity context
Pass the screen entity on each evaluation — not via setIdentity. See Entity & page context.
iOS is a client: local registerContext only. No PUT sdk/{appKey}/contexts.
Toggly.shared.registerContext("Order") { value in
let order = value as! Order // This mapper is called with your Order model.
return TogglyEntityContext(
kind: "Order", key: String(order.id),
attributes: ["Status": order.status]
)
}
let on = await Toggly.shared.isEnabled("OrderBadge", context: order, kind: "Order")
Gates fail closed without context. Identity is user only.
Next Steps
- Learn about SwiftUI Integration with property wrappers and view modifiers
- Explore UIKit Support for view controllers and extensions
- See Combine Publishers for reactive patterns
- Read about Configuration options
- Check Advanced Usage for identity management and events