23

Is there a way to find out the Scheme used at the run time ?

May be there is a better way to do this, I'm trying to set the Access Environment (Production vs Development) by using the Scheme name.

Currently I use #define ENV @"PROD" in App-Prefix.pch file to do this, but there is a chance to miss this when sending pkg to apple for review :(

2 Answers 2

43
+100

I searched far and wide for an answer to this because I really don't like the idea of creating extra Targets nor extra Configuration sets. Both of those options just create a huge Configuration synchronization problem.

So, after hacking Xcode for a couple of hours, this is what I came up with:

Step 1: Add the key "SchemeName" to your Info.plist with type string.

Step 2: Edit your default scheme and on Build -> Pre-actions add a new Run Script with the following:

/usr/libexec/PlistBuddy -c "Set :SchemeName \"$SCHEME_NAME\"" "$PROJECT_DIR/$INFOPLIST_FILE"

Make sure and select a target from under "Provide build settings from".

Step 3: Now duplicate that scheme as many times as you like (Manage Schemes... -> Select existing scheme -> Click gear icon -> Duplicate) For instance, you can create Development, Staging, Production, App Store, etc. Don't forget to click "shared" if you want these schemes carried around in version control.

Step 4: In the code, you can retrieve the value like this:

NSString *schemeName = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"SchemeName"];

Or in Swift:

let schemeName = Bundle.main.infoDictionary?["SchemeName"] as? String ?? ""

Now, the code can configure itself correctly at runtime. No nasty preprocessor macros to deal with and no brittle configuration mess to maintain.

UPDATE: According to the comments below, $PROJECT_DIR might need to be removed depending on where your Info.plist is located in your project.

Sign up to request clarification or add additional context in comments.

8 Comments

This is great and works! I set only the 'SchemeName' key in info.plist, and when I run the build the value is set. Here's my question: where does $SCHEME_NAME come from? I've searched the documentation for XCode environment variables (and the internet) and can't find any reference to it whatsoever.
Before I got it working, I had the Run Script command echo out all environment variables (Xcode sets a bunch before executing the script). I just then searched through it until I found a likely suspect.
For swift 4.2 use: Bundle.main.infoDictionary?["SchemeName"] as? String ?? ""
in XCode 11.4 I have to remove the $PROJECT_DIR/ part in the script, so it becomes: /usr/libexec/PlistBuddy -c "Set :SchemeName \"$SCHEME_NAME\"" "$INFOPLIST_FILE"
I'm currently running Xcode 12.5 and your original pre-action run script is the correct one. It doesn't matter which Xcode version you're using, but rather where your Info.plist file is placed within your project directory.
|
8

When running an app on the simulator or on your device, the DEBUG variable is set, allowing you to use it from your code:

#ifdef DEBUG
    // Something
#else
    // Something else
#endif

You can see this variable from your target's build settings:

As soon as the Run configuration is set on Debug (Product -> Scheme -> Edit Scheme), this variable will be set:

enter image description here

1 Comment

Yeah, doing this using the Build Configuration is likely better than inferring it via the Scheme, since build configuration also affects lots of other build settings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.