7ball
7ball

Reputation: 2315

Xcode building different environments for the same app

I have an app that talks to a server. I have 2 versions of this server: a production one and a testing one. This means I'd need to have a production iOS app and a testing iOS app. The logic is essentially the same for both versions of the app, except it would need to use certain configurations depending on which server it connects to. Right now, my solution is to use a plist file that contains informations that the 2 versions need. The plist would contain a bunch of key-value pairs like:

url: test-server.domain.com
username: test-subject
password: test-password

I have 2 git branches: a production branch and a testing branch for each of the iOS app version. The content of the said plist file would be different on each branch.

Question is: is there a more elegant way to solve this? Preferably I'd like to only have 1 branch. I've looked into using Xcode's environment variables, but those don't stick when I archive/build my apps.

Upvotes: 2

Views: 1683

Answers (2)

jbehrens94
jbehrens94

Reputation: 2396

There sure is! You can do this with environment variables, as described in this blogpost: Flavors for iOS. You can even switch app icon and app name based on the variables when building, therefore, you can check in code in the following way: if #APP_DEV // call dev API ELSIF // call prod API.

Steps

1: On the project settings level, duplicate the debug configuration and rename it to staging. (Optional)

2: Open the project build settings and add some user-defined settings: APP_ENV with values dev => dev, staging => stage, production => prod.

3: You need multiple bundle IDs to load apps side by side (for instance a beta or production app). Therefor, create another user-defined settings APP_BUNDLE_SUFFIX with the value .$(APP_ENV:lower). This turns Dev into .dev. Leave production empty if you like to have no extra suffix when submitting the app.

4: Append the APP_BUNDLE_SUFFIX to your product bundle ID (com.testapp.YourCoolApp.$(APP_BUNDLE_SUFFIX)).

5: In Swift projects, you can add the added variables to the "Active Compilation Conditions" on the same screen. Do this by adding ENV_$(APP_ENV) to the environments listed. In Objective-C projects, this can be done by adding the environments to the "Preprocessor macro's", but pay attention, you'll need to suffix =1 to the value in order to activate the variables.

Making the env vars stick

You might need to create separate schemes to achieve this. You can duplicate schemes, or option+click on the scheme at the top and switch the build config.

Upvotes: 2

Ryan
Ryan

Reputation: 4884

I usually use Preprocessor Macros for this.

Define variable like DEBUG for Debug and nothing in Release.

enter image description here

And then use this like

enum AppConfig {
    case debug
    case testFlight
    case appStore

    var host: String {
        switch self {
            case .debug: return "test host"
            default: return "production host"
        }
    }

    static var current: AppConfiguration {
        #if DEBUG
            return .debug
        #else
            if Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" {
                return .testFlight
            } else {
                return .appStore
            }
        #endif
    }
}

Wherever you want to use host, you can use AppConfig.current.host. The only thing you need to do is create scheme for debug and release.

Upvotes: 0

Related Questions