Skip to content

Instantly share code, notes, and snippets.

@farski
Last active August 29, 2015 13:57
Show Gist options
  • Save farski/9763168 to your computer and use it in GitHub Desktop.
Save farski/9763168 to your computer and use it in GitHub Desktop.

Generally my configuration plan looks something like this:

  • A root .xcconfig file called Common.xcconfig. This includes nearly all of buid settings, app configuration, etc
  • A Development.xcconfig file that overrides a few things like ONLY_ACTIVE_ARCH (inherts from Common)
  • Debug.xcconfig (inherits from Development)
  • Beta.xcconfig (inherits from Development)
  • Release.xcconfig (inherits from Common)

I make sure to have an xcconfig for each Build Configuration I have set up for the project. That makes it really easy to do things like define specific icons for different build types, and obviously all the other normal build flags you would need.

In your case you may want to go a step further and have xcconfigs for each target, and just do the inheritance a little differetly to suit your needs.

Once I have that setup, I generally end up with no target-level build settings on the Xcode project, aside from code signing. It keeps things very clean.

For defining service-level settings (like the base URL from an API), usually I avoid doing that directly in the xcconfigs. One pattern I commonly use is to have a macro in each build configuration xcconfig (eg SERVICES_CONFIGURATION = Debug, SERVICES_CONFIGURATION = Beta, etc), and then I'll expose the value in the info.plist (key: Services Configuration, value: ${SERVICES_CONFIGURATION}. Then I can know what service config I should be using at runtime (NSBundle.mainBundle.infoDictionary[@"Services Configuration"]).

You could either use that directly with some logic in your code, but since most of the apps I work on end up hitting a bunch of APIs and services, I tend to add one more level of abstraction, to help keep things organized.

I will add another record to my Info.plist: a dictionary of services and the various bits of info that are associated with each: the base URL, keys, secrets, etc. If I use the same info regardless of build config (eg TestFlight, Crashlytics) I'll have those key/values directly under the service. If I need to switch between keys based on environment (like for staging servers, Google Analytics, etc), I will have keys that match the build configs under the service, and then the actual values underneath that.

I then use a category on NSBundle that is smart enough to just pick the values I need when I request a piece of info for a given service.

The whole things requires a bit of time and effort upfront, but I reuse the setup in nearly all of my apps and it really reduces headaches down the road.

This unfortutnately gets a bit more complicated if you use CocoaPods, because it generates it's own xcconfig, and you end up having to do some more overrides or have that Common.xcconfig inherit from Pods.xcconfig and you have to do some copy/pasting every time you install/update the pods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment