Often times we find ourselves in a situation wherein the project has to be configured to make use of different provisioning profile and signing certificates and also with different bundle identifiers. The source code is maintained in a distributed and the vendor and the client make their own builds using their respective profiles, certificates and app ids.
This happens when the client and vendor cannot share their provisioning profiles or signing entities or in many cases the app ids as well because no two accounts can have the same app id.
In these situations it often becomes a hassle to change the project settings every time after one party pushes the code and other party wants to make a build. Each party would push the project file with their own provisioning profile, signing and app id settings. The practice of having to change these settings become a frustrating task over time.
A better way to manage this kind of situations is to use the Xcode configuration files called xcconfig files. They are widely used by many developers, but this article blog attempts to explain how it can be used to make the build settings management easier.
Basically you start with a xcconfig file say Version.xcconfig. This file will be your configuration setting for the app version.
VERSION=1.0
BUILD_NUMBER=1
Then you create another xcconfig file say Vendor.xcconfig that contains the app id, profile and signing certificate information.
BUNDLE_IDENTIFIER=com.vendor.myapp
CODE_SIGN_IDENTITY[sdk=*]=iPhone Developer
PROVISIONING_PROFILE[sdk=*]=D96971CA-FA3D-4A2D-89DB-B0F296893131
The provisioning profile UUID is the identifier of the current profile which you can obtain from the Provisioning Profiles section of the iPhone Configuration Utility. You should have this profile installed on your Mac.
The code signing identify can be set to iPhone Developer so that the Xcode automatically takes the one that matches the profile.
The bundle identifier can be used to set the app id of your configuration used for the testing at vendor’s end.
Once you have this file create a similar file called Client.xcconfig and specify the client specific settings. You can ask the client to fill in these details at their end.
You have to include the Version.xcconfig file in the other two config files so that both you and the client share the same version information for the applications built at your respective ends. If required you can avoid this and have your own version number too by specifying the version and build number properties in the respective configuration files.
Once you have the xcconfig files ready add them to the project but don’t include them in any target. Just add them so that they are visible in the file hierarchy of the project file.
Now edit the Project settings so that it makes use of these configuration files. By default there are Debug and Release configurations for a project. You can either use them or create new configurations called VendorConfig and ClientConfig and then set the respective xcconfig files in the ‘Based on Configuration File’ setting.
In the Info.plist file set respective properties to their respective environment variables.
For e.g. Set ${VERSION}
for CFBundleShortVersionString and ${BUILD_NUMBER}
for CFBundleVersion and ${BUNDLE_IDENTIFIER}
for the CFBundleIdentifier properties.
Now you are set to easily change the configurations without having to change a lot of things at different places. You can also create build schemes that will automatically take the vendor configuration for building thus using the vendor specific profile, certificate and app ids for making the builds.
This approach can also be used to make use of different identifiers related to third party SDKs by using the GCC_PREPROCESSOR_DEFINITIONS
variable in the xcconfig file. For e.g. you can specify your own Parse app id and secret in the Vendor config file and use the macros in the application code.
GCC_PREPROCESSOR_DEFINITIONS=$(GCC_PREPROCESSOR_DEFINITIONS) PARSE_APPID="@"1234567890"" PARSE_CLIENTSECRET="@"9876543210""
Using this approach you don’t have to change the source code to point to different instance when building for client and vendors. The project will automatically pick it from the xcconfig files and make use of the correct settings.