How can I access a user-defined Xcode build setting?

If I added a user-defined setting in my build configuration, how can I read that setting in my Objective-C code?

I have two files in my project, debug.plist and release.plist. I want my MainApp.m file to read one of these files based on which build configuration is running. I set up a user-defined setting named "filename" in both the Debug and Release configurations to point to the appropriate file. But I don't know how my MainApp.m file can read the filename variable from the current running configuration.


Here's what I did, I'm not 100% sure if this is what you're after:

  1. Go into the build Settings panel and choose the gear icon in the bottom left: add User-Defined Setting
  2. Create your user defined setting, for example:

    MY_LANG -> en_us
    
  3. Then, in the Preprocessor Macro's setting, you can reference that value:

    LANGCODE="$(MY_LANG)"
    

Now you can refer to LANGCODE in all your source files, and it will be whatever you filled out in your custom build setting. I realize that there's a level of indirection here, but that is intentional in my case: my XCode project contains a bunch of different targets/configurations with their own preprocessor macro's. I don't want to have to go into all of those, just to change the language code. In fact, I define the language code on the project level. I also use MY_LANG in a couple scripts, so just a preprocessor macro wouldn't do. There may be a smarter way, but this works for me.


You can access your user-defined build setting at run-time (as suggested in a comment by @JWWalker)

  1. Add an entry to your Info.plist file, and set it to your User-defined Build Setting

    MySetting -> ${MYSETTING}
    
  2. Read its value from code

    Objective-C

    [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MySetting"];
    

    [Edit] Swift

    guard let mySetting = 
      Bundle.main.object(forInfoDictionaryKey: "MySetting") as? String 
        else { print("MySetting not found") }
    

Swift 4

Lets say "filename" is the String you need in your app.

Add filename=YOUR_STRING to user-defined setting(for debug and release).

And add filename = $(filename) to info.plist.

Then in Swift code:

if let filename = Bundle.main.infoDictionary?["filename"] as? String {
    // do stuff with filename
} 
else {
    // filename wasn't able to be casted to String
}

Your code can't read arbitrary build settings. You need to use preprocessor macros.

EDIT: For example, in the target settings for the Debug configuration, you could add DEBUGGING=1 in the Preprocessor Macros build setting, and not define DEBUGGING in the Release configuration. Then in your source code you could do things like:

#if DEBUGGING
  use this file
#else
  use the other one
#endif