PVFeatureFlags/README.md
A Swift feature flags library that supports remote configuration, version control, and app type restrictions. Built with SwiftUI support and compatible with iOS/macOS/tvOS.
@StateObject and environment supportAdd the following to your Package.swift file:
dependencies: [
.package(url: "https://github.com/yourusername/PVFeatureFlags.git", from: "1.0.0")
]
Or add it directly in Xcode:
Create a JSON file with your feature flags configuration:
{
"features": {
"inAppFreeROMs": {
"enabled": true,
"minVersion": "1.0.0",
"minBuildNumber": "100",
"allowedAppTypes": ["standard", "standard.appstore"],
"description": "Allows downloading free ROMs directly in the app"
}
}
}
Add the PVAppType key to your Info.plist with one of these values:
standard - Standard non-App Store versionlite - Lite non-App Store versionstandard.appstore - Standard App Store versionlite.appstore - Lite App Store version<key>PVAppType</key>
<string>standard</string>
import PVFeatureFlags
// Check if a feature is enabled
if PVFeatureFlagsManager.shared.inAppFreeROMs {
// Feature is enabled
}
// Load remote configuration
Task {
try? await PVFeatureFlagsManager.shared.loadConfiguration(
from: URL(string: "https://your-domain.com/features.json")!
)
}
struct ContentView: View {
@StateObject private var featureFlags = PVFeatureFlagsManager.shared
var body: some View {
if featureFlags.inAppFreeROMs {
Text("Free ROMs feature is enabled!")
}
}
}
// In your App file
@main
struct MyApp: App {
@StateObject private var featureFlags = PVFeatureFlagsManager.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(featureFlags)
.task {
try? await featureFlags.loadConfiguration(
from: URL(string: "https://your-domain.com/features.json")!
)
}
}
}
}
// In your views
struct ContentView: View {
@Environment(\.featureFlags) var featureFlags
var body: some View {
if featureFlags.inAppFreeROMs {
Text("Free ROMs feature is enabled!")
}
}
}
{
"features": {
"featureKey": {
"enabled": true, // Required: Base enable/disable
"minVersion": "1.0.0", // Optional: Minimum app version
"minBuildNumber": "100", // Optional: Minimum build number
"allowedAppTypes": ["standard"], // Optional: Allowed app types
"description": "Feature description" // Optional: Feature description
}
}
}
The library supports four app types:
standard: Regular non-App Store versionlite: Lite non-App Store versionstandard.appstore: Regular App Store versionlite.appstore: Lite App Store versionYou can check app type properties:
let appType = PVAppType.standard
appType.isAppStore // false
appType.isLite // false
let customFlags = PVFeatureFlags(
appType: .standard,
buildNumber: "101",
appVersion: "1.1.0"
)
let manager = PVFeatureFlagsManager(featureFlags: customFlags)
// Check any feature by key
if PVFeatureFlagsManager.shared.isEnabled("customFeature") {
// Feature is enabled
}
The library includes testing-specific APIs to help with unit testing:
// Create a feature flags instance with pre-loaded configuration
let testFlags = PVFeatureFlags(
configuration: myTestConfig,
appType: .standard,
buildNumber: "101",
appVersion: "1.1.0"
)
// Or set configuration after initialization
let flags = PVFeatureFlags(appType: .standard)
flags.setConfiguration(myTestConfig)
Note: These testing APIs are marked as internal and are only available when importing the module with @testable.
The library is designed to be thread-safe:
This library is released under the MIT license. See LICENSE for details.