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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…