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

Objective CXcode

Objective C Problem Overview


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.

Objective C Solutions


Solution 1 - Objective C

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.

Solution 2 - Objective C

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") }
    

Solution 3 - Objective C

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
}

Solution 4 - Objective C

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

Solution 5 - Objective C

I tried zmippie suggestion but it didn't work for me.

I got it working with this:

${MY_LANG}

Solution 6 - Objective C

In case anyone else is still stuck looking for how to do preprocessor macros, look for the Apple LLVM - Preprocessing section in Build Settings. Under it, you will see a section called Preprocessor Macros.

This is where by default, Xcode inserts the DEBUG=1 macro for the debug build configuration.

You can add your own here, and give them different values for debug, release and any custom build configs you may have.

To add one, double-click on the current value list for the config you want, and it'll display a nice little editor with one macro on each line. Just add your own macro name, and give it a value the same way the DEBUG one is done.

These can be checked during the preprocessor build phase using #if, #ifdef etc. to provide conditional code or values.

Hope that helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThe Lazy HikerView Question on Stackoverflow
Solution 1 - Objective CzmippieView Answer on Stackoverflow
Solution 2 - Objective CAndyDeveloperView Answer on Stackoverflow
Solution 3 - Objective CKristianView Answer on Stackoverflow
Solution 4 - Objective CJWWalkerView Answer on Stackoverflow
Solution 5 - Objective CMorten HolmgaardView Answer on Stackoverflow
Solution 6 - Objective CSimon TillsonView Answer on Stackoverflow