It is a best practice the separation of configuration from code.
In this article we will use Configuration Settings File to achieve this.
According to Apple (https://help.apple.com/xcode/mac/current/#/dev745c5c974)
A Configuration Settings File (a file with a .xcconfig file extension), also known as a build configuration file or xcconfig file,
is a plain text file that defines and overrides the build settings for a particular build configuration of a project or target.
This type of file can be edited outside of Xcode and integrates well with source control systems. Build configuration files adhere to specific formatting rules, and produce build warnings if they do not.
And that brings us to what is a build setting?
According to Apple (https://help.apple.com/xcode/mac/current/#/dev382dac089)
A build setting provides information necessary for building the product of a target. For each task performed during the build process—such as compiling Swift code—build settings control how that task is performed.
Values on the xcconfig files will override the values from the build settings.
The syntax is simple
e.g
1 |
A_KEY = 1 |
every value si considered string and “//” is for commnets
If we want to have a url as value we have to escape it:
1 |
https:/$()/google.com |
some extra capabilities are:
– include build settings from other xcconfig files
1 |
#include "AnotherFile.xcconfig" |
– reference other values
1 2 |
A_KEY = 1 ANOTHER_KEY = $(A_KEY) |
To add an xcconfig we have to crate a Configurations Settings File:
The we have to add the configuration file to the configuration set of the target:
In order to have access to the config values we have to add them to the Info.plist:
And we can add write code to access them:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Code copied from: https://nshipster.com/xcconfig/ enum Configuration { enum Error: Swift.Error { case missingKey, invalidValue } static func value<T>(for key: String) throws -> T where T: LosslessStringConvertible { guard let object = Bundle.main.object(forInfoDictionaryKey:key) else { throw Error.missingKey } switch object { case let value as T: return value case let string as String: guard let value = T(string) else { fallthrough } return value default: throw Error.invalidValue } } } |
Resources: