In a non-trivial application, you probably have more than just a single environment for your project and you would find it difficult to manage the many environments and configurations manually in the code.
In this post we will tackle this issue using Xcode configuration files, and we will see how we can switch between configurations without manually modifying our codebase.
Use Case
You have an app that has different environments namely local, staging, and production. Each environment requires different configuration; the endpoints are different, the product app is different, as you want to have different app for each environment where each app has different app icon and name for example. Another ability you want, is that on staging / local builds you want to be able to use some debugging tools like Inspector or capturing network calls but not on App Store version for instance.
Setting up
- Go to your beloved IDE Xcode :). Create a new project or open an existent project. Since in the end we won’t to test our release App(s) you should have a valid App id (creating app ids and profiles is handled automatically by Xcode these days), so you should have access to an apple account with sufficient permissions to create certificates…
- Create a folder called
Configurations
to make it easier to spot your configuration files, in the configurations folder lets create configuration files by clicking right click and selecting new file which will open a window to select the type of the file, in the search box type config and you will see a file with Configuration Settings File, select it and click next , now name it something likeStaging-Debug
, keep doing this and createStaging-Release
,Production-Debug
, andProduction-Release
. “You can have as many configurations as you wish , we will stick with 4 , for this tutorial”. - We will be having 2 products with different App Ids , you can name them the way you wish based on your app. for me they will be
com.whitetorch.Configuragtions
(Appstore/production version) andcom.whitetorch.Configuragtions.staging
for staging environment. - To achieve that without create a target for each one, we will have to play around the
product bundle identifier
. In the configuration files create a new setting with namePRODUCT_BUNDLE_ID = <#the App id for configuration#>
, e.g. for Staging configuration files it will bePRODUCT_BUNDLE_ID=com.whitetorch.Configuragtions.staging
and for production configuration files something likePRODUCT_BUNDLE_ID=com.whitetorch.Configuragtions
. - Now head to
Targets -> choose app target -> build settings
and findProduct bundle identifier
setting in the Packaging section , you will find the bundle id specified explicitly but since we want it be configurable , change it to$(PRODUCT_BUNDLE_ID)
. - Go to the
Project (the blue icon with the project name) -> Info -> Configurations section
, duplicate Debug and name it Staging-Debug, also duplicate Release and name it Staging-Release, and leave the original for production configurations but you can also rename them. - Select each configuration and select the matching configuration file name from the drop down list a long the project name.
if you go back to the target->build settings -> product bundle identifier
, you will see the correct bundle id is listed for each configuration. Also if you go to Signing and Capabilities tab , you will see that Xcode spectated both bundle identifier meaning you can actually use different teams đ which can be useful say you building a product for a client , you can only have the production id on the client apple account, and other stuff on your development account.
Cool!! Lengthy steps!!! !^_^.
Let’s actually use that!
Configure the schemes:
Select the only Scheme we have setup by Xcode and click on edit scheme , that will be our production scheme so we will leave the configurations as is , but make sure that “Run” has Debug build configuration, and archive has Release build configuration.
Click on Manage Schemes and rename the selected scheme to be Production App , to make it easier to distinguish.
go back to edit Scheme window and click on “Duplicate Scheme” this time change the build configuration for Run to be “Staging-Debug” and for Archive to be “Staging-Release”. In Manage Schemes window make sure the Shared checkbox is selected for both Schemes.
Test it on simulator
Finally some demoing, select the “Production App” scheme and run it on your simulator or on a device.
Select the “Staging App” Scheme and run again on same place , you should be seeing two app icons with same name which means We are on the right track :).
Now we have a proof of concept for our strategy that we can build on it, so let’s do some more.
change the app name
in each configuration file create a setting and call APP_NAME. and set it , e.g. APP_NAME = Staging app
.
go to info.plist and add a new key , just select any row and press Enter, and type Bundle display name, and in the value field type $(APP_NAME)
, this means set the displayed name on springboard/search/settings app to the APP_NAME
setting we provided earlier.
Use that in code to change View Color/Theme
As you saw before to use the settings in the Xcode level we can wrap it with $(setting_name)
, but we can’t do that alas in our code. and to achieve that we need another way.
- Let’s create a new property list file and name it configuration.plist, inside it we create two new keys with Dictionary type. namely
Staging
andProduction
, under each key create a new key with String type and name itcolorName
. Now we have Staging and Production dictionaries where each has one key namedcolorName
, which will be used to determine the view color of your choice.
- Head to info.plist and create a new Key and name it ‘Environment’ of type String and in the value field type
$(Environment)
, now head to the configurations files xcconfig files and add new setting, name it ‘Environment’ and set a value for it matching the name we used in the configuration.plist file, so for Stage-Debug andStaging-Release.xcconfig
we addEnvironment=Staging
and so on.
- Let’s create a utility file to be able to parse the configurations from configurations.plist to avoid redundancy.
- Now head to the view you want to change its color and type
let colorName: String = AppConfigurations().get(key: AppConfigurationsKey.colorName)
let color = UIColor.init(named: colorName) self.view.backgroundColor = color
AppConfigurations
is a utility file , you can find it in the repo here.
make sure you add the color name in Assets.xcassets
file.
This is meant just as an example , you can have whatever you want , you can add and endpoint url for instance , or maybe Some SDK key, etc…
Cool!!! Now we have a tool that can let us achieve many things.
I will stop right here , it’s too long post already. maybe it will be followed with another post soon, as am planning.
You can find the project with the custom configurations here
https://github.com/MoathOthman/ConfigurationsExample
Useful links and references
build settings reference: https://help.apple.com/xcode/mac/10.2/#/itcaec37c2a6
Configuration Settings https://help.apple.com/xcode/mac/10.2/#/dev745c5c974
https://pewpewthespells.com/blog/xcconfig_guide.html