When building an application for iOS or OS X that integrates with a web service, it’s often handy to be able to use different servers depending on the environment. The usual case is I want to use this testing server while in development and all of my customers to use a different, production server.
One solution is to create some defines in your source code like below:
#define ROOT_URL @"http://test.myapi.example.com"
#define ROOT_URL @"http://myapi.example.com"
That solution certainly works. However it doesn’t feel as clean to me as it encourages tiger coupling of your API code with your application code. A cleaner solution is to embed the URL into your Info.plist file. A naive approach might be to simply add two entries, one for development and one for production such as follows:
There’s a few problems with the above. 1) You’re exposing your test server urls to end users, which is just asking for trouble and 2) You still need to test in code which key to use.
The best solution that I’ve found is a combination of two solutions above. Use the C pre-processor in our Info.plist. Using the solution below works great, though you will no longer be able to use Xcode’s built in plist editor. The Info.plist is invalid until it gets processed by the C pre-processor. Simple ctrl-click on the Info.plist file and click Open As -> Source Code. This will expose the raw XML.
You can then access this URL by the following:
NSDictionary *infoDict = [[NSBundle mainBundle] infoDict];
NString *url = [infoDict valueForKey:@"MyAPIRootURL"];
I like to add a define constant for the MyAPIRootURL, to reduce the likelihood of a type-o making difficult to find bugs.
Before you can use this, you must tell Xcode to preprocess your Info.plist file. Open your build settings and make them look something similar to the following:
Notice the Other preprocessor flags – the “-traditional” is important. Without this flag, the pre-processor will interpret the // in http:// as a C-style comment and read the line as http:, which is invalid. The -traditional flag only interprets /**/ C-style comments as comments, thus preventing the URL from mangling your XML.
Using the C pre-processor in your Info.plist can allow you to cleanly separate development and production settings while encouraging a looser coupling between API frameworks and application code.