A flexible, protocol-based feature flag system for Swift applications.
- 🎯 Type-Safe: Protocol-based design with Swift generics
- 💾 Persistent: Automatic storage via UserDefaults
- 🎨 SwiftUI Ready: Built-in UI components
- 🔧 Extensible: Easy to customize for any app
- 📱 Cross-Platform: iOS, macOS, tvOS, watchOS support
Add FeatureFlagKit as a dependency in your Package.swift:
dependencies: [
.package(url: "git@github.com:rickhohler/FeatureFlagKit.git", from: "1.0.0")
]Or add it via Xcode: File → Add Packages → Enter repository URL
import FeatureFlagKit
enum MyFeatureFlag: String, FeatureFlagProtocol {
case darkMode
case experimentalUI
var displayName: String {
switch self {
case .darkMode: return "Dark Mode"
case .experimentalUI: return "Experimental UI"
}
}
var description: String {
switch self {
case .darkMode: return "Enable dark mode throughout the app"
case .experimentalUI: return "Try the new experimental interface"
}
}
var icon: String {
switch self {
case .darkMode: return "moon.fill"
case .experimentalUI: return "sparkles"
}
}
}@MainActor
class AppFeatureFlags {
static let shared = FeatureFlagManager<MyFeatureFlag>(
storageKey: "com.myapp.featureFlags"
)
}struct SettingsView: View {
@ObservedObject var manager = AppFeatureFlags.shared
var body: some View {
Form {
Section("Experimental Features") {
ForEach(MyFeatureFlag.allCases) { feature in
FeatureFlagToggleView(
feature: feature,
isEnabled: Binding(
get: { manager.isEnabled(feature) },
set: { manager.setEnabled(feature, enabled: $0) }
)
)
}
}
}
}
}if AppFeatureFlags.shared.isEnabled(.darkMode) {
// Show dark mode UI
}Set features to be enabled by default:
var defaultValue: Bool {
switch self {
case .darkMode: return true // Enabled by default
case .experimentalUI: return false
}
}Add configuration screens for complex features:
var hasConfiguration: Bool {
switch self {
case .experimentalUI: return true
default: return false
}
}// Check if enabled
manager.isEnabled(.darkMode)
// Enable/disable
manager.setEnabled(.darkMode, enabled: true)
// Toggle
manager.toggle(.darkMode)
// Reset to defaults
manager.resetToDefaults()- Swift 5.10+
- iOS 15.0+ / macOS 12.0+ / tvOS 15.0+ / watchOS 8.0+
MIT License - See LICENSE file for details
Rick Hohler