Skip to main content

iOS SDK

Use Toggly's native iOS SDK in Swift applications for iOS, macOS, tvOS, and watchOS.

Quick reference

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​

PackageDescription
TogglyCoreCore functionality, storage, and API client (required)
TogglySwiftUISwiftUI property wrappers, view modifiers, and views
TogglyUIKitUIKit extensions and view controller support
TogglyCombineCombine 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​

  1. File → Add Package Dependencies
  2. Enter: https://github.com/ops-ai/Toggly.FeatureManagement.git
  3. 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​