I'm a JavaScript web app developer that has just inherited a legacy iOS app. The app is full of hardcoded URLs that point to our production API.
I'd like to factor out the Base URL into a constants file, or an environment variables file, or a config file, so that a different Base URL can be used in different environments (dev, staging, production).
What's the best practice in the land of the Swift?
Is there something similar to a .env
file I can use?
CodePudding user response:
Some recommend creating a config file (.xcconfig) for every environment and then you can set up your different base URL there.
Where I used to work, we used a constants file where we set up different values, urls,ports and so on depending on the environment like this:
#if DEBUG
let a = 2
#if PRODUCTION
let a = 4
I think this is the best thing to do.
CodePudding user response:
What I always do is probably a more flexible approach than checking constants in your code and littering different values of the same variable per environment everywhere.
It is not necessary to create .xcconfig files either.
Setting up the whole thing is a little more work but you will see that it is very easy to use afterwards.
In my example you see how I set different REST endpoints for production/UITest/development builds in my
Make sure to set its value to the name you chose, enclosed in $()
(brackets, not braces!), in my case it's $(TS_WEBSERVICE_URL)
.
Build settings
In your build settings tab, add custom "user defined" build parameters, again with the same name:
You see that you can define values for Debug, UITests and Release. And that I use this mechanism for a whole lot of things that are different in the environments.
Adding more environments
If you need more environments, add them on your master project node's Info tab (like I probably did here with UITests
):
Use the values in code
Now for the easy part: use your newly defined values in your code. It all boils down to getting an NSBundle instance and reading the value defined in your Info.plist
which has been substituted automatically during build process.
Objective C:
NSString *webserviceURL = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"TS_WEBSERVICE_URL"];
Swift:
let webserviceURL = Bundle.main.object(forInfoDictionaryKey: "TS_WEBSERVICE_URL") as! String
Just one line of code per environment setting.
One thing I have not shown, but which is also fairly easy: just define a category to NSBundle
and supply new methods called webserviceUrl
and similar methods. They can then be called like this: Bundle.main.webserviceUrl()
which even more simplifies the source code.