Skip to content

Environments

Jakub Olejník edited this page Sep 29, 2020 · 12 revisions

We usually need to use different settings and parameters for different environments. For example API URLs, tokens and keys for 3rd party services, plists for Firebase etc. Our template contains complex set of tools to easily resolve this common issue.

Schemes

Scheme == Environment

schemes

You can see 3 schemes in Xcode project. There is a special scheme for each environment. We usually use these 3 environments:

  1. Development - for development 💡
  2. Stage - for testing, QA, presentations for our customers
  3. Production - for AppStore

Each scheme contains a short pre-build action with 2 commands. At first environment info is written to a hidden file which is then used in build phases. That's because you have no info about running scheme (and scheme == environment) in build phase, so we pass it through a file. Second action is a generation of a plist preprocess header. This must be done in scheme pre-action to have header available before build starts. Otherwise build would fail.

pre-action

Build configurations

Each environment can be built with 3 different build configurations:

  1. Debug - for running on dev's device
  2. Beta-Developemt - builds for QA with development API
  3. Beta-Stage - builds for QA with stage API
  4. Beta-Production - builds for QA with production API
  5. Release

Besides different build settings like optimization level, bitcode etc. there is a different bundle ID for each configuration. We usually use this pattern:

  1. Debug - cz.ackee.appName.debug
  2. Beta-Development - cz.ackee.appName.development.beta
  3. Beta-Stage - cz.ackee.appName.stage.beta
  4. Beta-Production - cz.ackee.appName.production.beta
  5. Release - com.company.appName

It is tied with code signing settings and it also allows you to install eg. debug and appstore versions on one device.

Build phases

There are 3 build phases connected with environment switching.

Environment switch

Folder Environment contains folders for all environments. This script copies all files from selected environment's folder to folder named Current, where files from Current are linked/bundled to project.

Our template contains only one file now - environment.plist and folder with Google plists, but you can add more of course.

Generate environment file

File environment.plist mentioned above is the place for your base URL, tokens etc. In this build phase swift enums are automatically generated from this file so all environment variables are accessible in your codebase as enum cases (see file Environment.swift).

The generator script supports almost all value types that plist can hold, but there are some conventions.

Supported types:

  • Dictionary - generated as nested enum, first letter is capitalized
  • URL - string whose key has suffix URL and can be converted to URL
  • Bool - bool or number whose key has prefix is and can be converted to Bool (plist serialization cannot determine between true/false and 0/1)
  • Int
  • Double
  • Date
  • Data

Select GoogleService-Info.plist

We (and a lot of other developers) use Firebase in our apps and as you know, Firebase is configured via downloaded plist file. This file is unique for each bundle ID so we need 3 different plists.

But when you need to use eg. Firebase realtime database in different environments you need more then one firebase project.

That's why we have GoogleService folder with 3 plists in each environment folder. This folder is copied within environment switching phase. In this phase the right file is selected according to build configuration. It's just copied to GoogleService-Info.plist.


Continue to Extensions ➡️

Clone this wiki locally