Contents

philiprehberger/swift-feature-flags

Type-safe feature flags with local defaults, remote overrides, and SwiftUI integration

Requirements

  • Swift >= 6.0
  • macOS 13+ / iOS 16+ / tvOS 16+ / watchOS 9+

Installation

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/philiprehberger/swift-feature-flags.git", from: "0.1.0")
]

Then add "FeatureFlags" to your target dependencies:

.target(name: "YourTarget", dependencies: [
    .product(name: "FeatureFlags", package: "swift-feature-flags")
])

Usage

import FeatureFlags

// Define flags with defaults
let registry = FlagRegistry()
await registry.register([
    LocalProvider(flags: [
        "dark_mode": true,
        "max_items": 50,
        "welcome_message": "Hello!"
    ])
])

// Check flags
let darkMode = await registry.isEnabled("dark_mode")  // => true
let maxItems: Int = await registry.value(for: "max_items", default: 10)  // => 50

@Flag Property Wrapper

struct AppFlags {
    @Flag("dark_mode", default: false) var darkMode
    @Flag("max_items", default: 10) var maxItems
    @Flag("welcome_message", default: "Hi") var welcomeMessage
}

Remote Overrides

let remote = RemoteProvider(url: URL(string: "https://api.example.com/flags.json")!)
await registry.register([
    LocalProvider(flags: ["dark_mode": false]),  // default
    remote  // overrides local when available
])
await try registry.refresh()  // fetch remote flags

A/B Testing

let test = ABTest(key: "onboarding_flow", variants: ["control", "variant_a", "variant_b"])
let variant = test.variant(for: userId)  // deterministic per user

Debug Overrides

await registry.override("dark_mode", value: true)  // force-enable for debugging
await registry.clearOverrides()

API

FlagRegistry

| Method | Description | |--------|-------------| | register(:) | Register flag providers in priority order | | value(for:default:) | Get a typed flag value with fallback | | isEnabled(:) | Check if a boolean flag is true | | refresh() | Refresh all remote providers | | override(_:value:) | Override a flag locally for debugging | | clearOverrides() | Clear all manual overrides |

FlagProvider

| Method | Description | |--------|-------------| | value(for:) | Return a flag value or nil | | refresh() | Refresh flag data from source |

ABTest

| Method | Description | |--------|-------------| | variant(for:) | Deterministic variant for a user ID |

Development

swift build
swift test

Support

💬 Bluesky · 🐦 X · 💼 LinkedIn · 🌐 Website · 📦 GitHub · ☕ Buy Me a Coffee · ❤️ GitHub Sponsors

License

MIT

Package Metadata

Repository: philiprehberger/swift-feature-flags

Default branch: main

README: README.md