Feature Flags for iOS developers
By: Alex Logan
Tags: Agile, Swift, iOS, Feature, Development

Implementation

Feature flags can and should be built simply to begin with. You can extend these later with things like the previoulsy mentioned run-time customisation, but its not needed to get started.

We’re going to be using Swift for this example, but you could easily replicate this in Kotlin , Javascript, Dart or others for the platform you’re on.

We simply have a list of features and a basic switch that enables or disables them. Defaulting to false creates a safety first situation that should help prevent features that aren’t ready from sneaking into your next release. A great way to extend this would be to store values in user defaults, core data, or even make them configurable in an .xcconfig file so you can have targets for each feature.

Using a feature flag

Having the feature flag is only the beginning. Now, we actually have to use it.

Feature flags tend to expose spaghetti code very quickly, as you’ll notice loads of these if Feature.loyalty.isEnabled 's scattered throughout your codebase. If this starts to happen, consider a refactor to de-couple your code before you start to add these.

We’ll look at three different examples here, a View in SwiftUI, a ViewModel, and a UIKit view.

SwiftUI

SwiftUI’s view builders seem like they were built for these. You can now use control flow in your view code, and add views based on the flag being enabled.

Here’s our view before we have a feature flag and the new code.

Now, lets add our feature flag. All we have to do is make sure to add the @ViewBuilder attribute, and a quick if statement for our loyalty feature.

This adds our new feature and shows the new view for us, in one if statement.

If we go into our feature file, and make the following change:

We’ll see the following when we run our app.

There’s absolutely no trace of our new feature, and we could release our app with that tab being invisible — great!

View Models

Something a little more complicated, is the changes you might have to make to your viewmodels. If you don’t use MVVM, feel free to skip this section.

There’s a couple steps we need to take here to make sure that we can properly use feature flags with view models. The first, is to extract a protocol for our View model. The example one we’re going to use fetches a list of orders, and will be extended after this to fetch the users stamps.

Extracting a protocol, is easy. By doing this, we can change the type our view references, and inject in a different view model depending on what state we’re in. A good approach if you’re building apps where you know you’ll be using feature flags, is to build this protocol driven way from the start.

Now we’ve done that little refactor, we can build our new view model, that has some extra little properties on it.

Here, we’ve been able to hide away the extra features behind both a feature flag and a type check. This means that in a higher level view we can inject the correct view model and also ensure the feature flag is set correctly. When this feature is eventually released, we can add the properties to the protocol, use our new view model only, and remove both the checks in our if statement — neat!

UIKit

Something i’ve come across a few times with feature flags, is that they tend to fall apart when you have a storyboard. You can’t change the storyboard and hide that behind a feature flag, so you have to make a compromise:

Add the UI and make sure it gets turned off in code — which is easy to forget

Change the UI by adding it in code — creating a mix of programatic and interface builder designs

Accept that some of the UI will be different even with the feature turned off — this will happen in a feature where you’re not just adding something, you’re also rebuilding existing UI

My solution, is to use nibs for my view controllers. There’s many advantages of these ( which we won’t get into here ) but a great one — is being able to progranatucally pick which nib you want for a given view controller. This allows you to have two nibs for the same view controller, or simply present a whole different one instead. Lets look at those options in code.

Here is a typical way of presenting a nib-backed view controller in code.

Now, lets see the two different ways we can use our feature flag to change this code. The first option is to simply change the nib in our initialiser to use different UI.

The second way, is to give this responsibility to our co-ordinator or presenting view controller, this is arguably the correct way to do it, as a view shouldn’t have to decide if its showing a new or old version.

In both examples, we’ve managed to remove the need to create a whole second view controller, by just having a seperate UI file that backs the new UI. This allows for the old UI to remain completley intact.

Conclusion

Feature flags are a powerful tool that can help drive confidence in your product. Whatever technology you use to build your app, there’s a way to get feature flags in. We’ve talked about some advanced usage, like allowing users to change them at run time, or using xcconfigs, and these are all great additions you can make once you have these integrated into your development process.

Once you’re comfortable, you can even look at extending these. What if the answer to is this enabled came from a web service, or you addded A/B testing functionality to them?

There’s a lot of opportunity — give it a try.