When building an app, we often have the App Store version installed on our devices, but we also need to install the beta version, and if we want to have them both on the same device, we need to differentiate them. The best solution for that is to have different icons.

Same app, different configurations

Configurations

The first step is to create a configuration for each icon you want. For instance:

  • a Debug configuration for the dev environment,
  • a Beta configuration for the beta environment,
  • a Release configuration for the prod environment.

By default, the Debug and Release configurations are created, we can add a Beta configuration by duplicating an existing configuration.

Create multiple Configurations

App Icons

Next, we have to create several App Icons in the Assets.xcassets file. You can name them as you want, ideally, you want to create one App Icon per configuration.

Create multiple App Icons

Build Settings

In the Build Settings of your target, you need to specify the App Icon and the Bundle Identifier for each configuration.

Asset Catalog App Icon Set Name

By doing so, the App Icon will automatically be selected according to the current configuration.

Specify an Asset Catalog App Icon per configuration in the Build Settings

Product Bundle Identifier

Because an app is identified by its Bundle Identifier, we need to specify a different Bundle Identifier for each configuration. A different app will then be created for each Bundle Identifier.

Specify a Bundle Identifier per configuration in the Build Settings

Configuration in code

Sometimes you also want to detect the configuration in code, it’s especially useful for constants, like the domain of your API for instance. There are several ways to do this, the easiest one is to add some flags in the Build Settings.

Add flags in Build Settings

You can then access those flags in your code:

struct Constants {
    #if DEBUG
    static let domain = "dev.example.com"
    #elseif BETA
    static let domain = "beta.example.com"
    #else
    static let domain = "www.example.com"
    #endif
}

Of course, the goal is to avoid to use them in too many different files, that’s why I usually put all my constants inside this conditional statement.

Scheme

You can finally change the Build Configuration for your scheme if you want to compile the app on your device for a specific configuration.

Edit Scheme’s Build Configuration

Another solution would be to create a scheme for each configuration.

Fastlane

This is the icing on the cake, thanks to fastlane you can specify a configuration when building your app and the correct icon will automatically be selected.

lane :beta do
    # ...

    # Compile IPA
    gym(
        scheme: "ExampleApp",
        configuration: "Beta",
        use_legacy_build_api: true,
        clean: true
    )

    # ...
end

Conclusion

This solution is an easy way to create an app for each environment, and differentiate them with a different icon on your devices, but it’s not the only one.

And you, how you do when you’re in the same situation? Do you see some limitations using this solution?