SkillAgentSearch skills...

FeatureFlags

🚩 Allows developers to configure feature flags, run multiple A/B tests or phase feature roll out using a JSON configuration file.

Install / Use

/learn @rwbutler/FeatureFlags

README

FeatureFlags

Build Status Version Carthage compatible Maintainability License Reviewed by Hound

FeatureFlags makes it easy to configure feature flags, A/B and MVT tests via a JSON file which may be bundled with your app or hosted remotely. For remotely-hosted configuration files, you may enable / disable features without another release to the App Store, update the percentages of users in A/B test groups or even roll out a feature previously under A/B test to 100% of your users once you have decided that the feature is ready for prime time.

To learn more about how to use FeatureFlags, take a look at the keynote presentation, check out the blog post, or make use of the table of contents below:

Features

  • [x] Feature flags
  • [x] A/B testing and MVT testing
  • [x] Feature A/B testing (where a feature is enabled vs a control group without the feature)
  • [x] Host your feature flags JSON configuration remotely allowing you to enable / disable features without releasing a new version of your app
  • [x] Use an existing JSON file or host an entirely new configuration
  • [x] Adjust the percentages of users in each test group remotely
  • [x] Convert an A/B test into a feature flag once you have decided whether the feature test was a success i.e. rollout a feature to 100% of users
  • [x] Visualize the state of your flags and tests using FeatureFlagsViewController in debug builds of your app

What's new in FeatureFlags 3.0.0?

See CHANGELOG.md.

Installation

Cocoapods

CocoaPods is a dependency manager which integrates dependencies into your Xcode workspace. To install it using RubyGems run:

gem install cocoapods

To install FeatureFlags using Cocoapods, simply add the following line to your Podfile:

pod "FeatureFlags"

Then run the command:

pod install

For more information see here.

Carthage

Carthage is a dependency manager which produces a binary for manual integration into your project. It can be installed via Homebrew using the commands:

brew update
brew install carthage

In order to integrate FeatureFlags into your project via Carthage, add the following line to your project's Cartfile:

github "rwbutler/FeatureFlags"

From the macOS Terminal run carthage update --platform iOS to build the framework then drag FeatureFlags.framework into your Xcode project.

For more information see here.

Swift Package Manager

The Swift Package Manager is a dependency manager for Swift modules and is included as part of the build system as of Swift 3.0. It is used to automate the download, compilation and linking of dependencies.

To include FeatureFlags as a dependency within a Swift package, add the package to the dependencies entry in your Package.swift file as follows:

dependencies: [
    .package(url: "https://github.com/rwbutler/FeatureFlags.git", from: "2.0.0")
]

Usage

With the framework integrated into your project, the next step is configuration using a JSON file which may be bundled as part of your app or hosted remotely. The JSON file may be newly-created or could be an existing configuration JSON file that you're using already. Simply add a key called features at the top level of your file mapping to an array of features as follows:

{
    "features": []
}

The contents of the array depends on the feature flags and tests to be configured.

To let FeatureFlags know where to find your configuration file:

guard let featuresURL = Bundle.main.url(forResource: "features", withExtension: "json") else { return }
FeatureFlags.configurationURL = featuresURL

Or:

guard let featuresURL = URL(string: "https://www.exampledomain.com/features.json") else { return }
FeatureFlags.configurationURL = featuresURL

In the event that you opt to host your JSON file remotely, you may provide a bundled fallback as part of your app bundle:

guard let fallbackURL = Bundle.main.url(forResource: "features", withExtension: "json") else { return }
FeatureFlags.localFallbackConfigurationURL = fallbackURL

Your remotely-hosted JSON file will always take precedence over bundled settings and remotely-defined settings will be cached so that in the eventuality that the user is offline, the last settings retrieved from the network will be applied.

Feature Flags

In order to configure a feature flag add a feature object to the features array in your JSON configuration.

{
    "features": [{
        "name": "Example Feature Flag",
        "enabled": false
    }]
}

Then add an extension on Feature.Name to import your feature flag in code as follows:

import FeatureFlags

extension Feature.Name {
	static let exampleFeatureFlag = Feature.Name(rawValue: "Example Feature Flag")
}

Make sure that the raw value matches the string in your JSON file. Then call the following to check whether the feature flag is enabled:

Feature.isEnabled(.exampleFeatureFlag)) 

If the string specified in your Feature.Name extension doesn't match the value in your JSON file, the default value returned is false. If you need to check the feature exists, you can write:

if let feature = Feature.named(.exampleFeatureFlag) {
	print("Feature name -> \(feature.name)")
	print("Feature enabled -> \(feature.isEnabled())")
}

A/B Tests

To configure an A/B test, add the following feature object to the features array in your JSON file:

{
	"name": "Example A/B Test",
	"enabled": true,
	"test-variations": ["Group A", "Group B"]
}
  • enabled indicates whether or not the A/B test is enabled.

The only difference between a feature flag and an A/B test involves adding an array of test variations. FeatureFlags will assume that you are configuring an A/B test if you add two test variations to the array - add any more and the test will automatically become a multivariate test (MVT).

Import your feature into code with an extension on Feature.Name:

extension Feature.Name {
	static let exampleABTest = Feature.Name(rawValue: "Example A/B Test")
}

And then use the following to check which group the user has been assigned to:

if let test = ABTest(rawValue: .exampleABTest) {
	print("Is in group A? -> \(test.isGroupA())")
	print("Is in group B? -> \(test.isGroupB())")
}

Alternatively, you may prefer the following syntax:

if let feature = Feature.named(.exampleABTest) {
	print("Feature name -> \(feature.name)")
	print("Is group A? -> \(feature.isTestVariation(.groupA))")
	print("Is group B? -> \(feature.isTestVariation(.groupB))")
	print("Test variation -> \(feature.testVariation())")
}

Feature A/B Tests

A feature A/B test is a subtle variation on (and subtype of) an A/B test. In a generic A/B test you may want to check whether a user has been placed in the blue background or red background test variation. A feature A/B test specifically tests whether the introduction of a new feature is an improvement over a control group without the feature. Thus in a feature A/B test - the feature is either off or on.

To configure a feature A/B test use the following JSON:

{
	"name": "Example Feature A/B Test",
	"enabled": true,
	"test-variations": ["Enabled", "Disabled"]
}
  • enabled indicates whether or not the A/B test is enabled.
extension Feature.Name {
	static let exampleFeatureABTest = Feature.Name(rawValue: "Example Feature A/B Test")
}

By naming the test variations Enabled and `Di

Related Skills

View on GitHub
GitHub Stars599
CategoryDevelopment
Updated9d ago
Forks24

Languages

Swift

Security Score

100/100

Audited on Mar 15, 2026

No findings