• 3 min read
Versioning for iOS & macOS
Bundle version string, short and Bundle version keys in Info.plist files would always confuse me. However, gone are the days of my bewilderment. Extensive research, in addition to trial and error, have led me to a deeper understanding of this domain. Today, I want to share my story and helpful resources with others who may be struggling with iOS & macOS versioning.
As we all know, the property list keys in question are
CFBundleVersion. For Apple-only-knows-reason, there is just one constant—the
kCFBundleVersionKey global variable—and we can only dream about getting another.
Bundle version string, short. Let's start with CFBudnleShortVersion documentation. It's really close to Semantic Versioning 2.0.0. The only exception: it doesn't support any pre-release & build metadata (like
-rc.1 or even
-rc.2-build.32.45.6). It's crucial that “This key is used throughout the system to identify the version of the bundle.”
Bundle version. Let's continue with CFBundleVersion. This is another almost semantic version, but we have a difference: “This key is required by the App Store and is used throughout the system to identify the version of the build.”
The difference. The wonderful Technical Note 2420 explains how those two keys & numbers work together and even more. The tl;dr is that
CFBudnleShortVersion is your app version, as we understand it, and
CFBundleVersion is a build number for the system to differentiate builds of the same version. But there is one serious gem in this note:
For macOS apps, build numbers must monotonically increase even across different versions. In other words, for macOS apps you cannot use the same build numbers again in different release trains. iOS apps have no such restriction and you can re-use the same build numbers again in different release trains.
So what we have here is just two triples of integers. If some of you want to make a pile of metadata (long time intervals, commit hashes) in
CFBundleVersion (build numbers) with integers, I need to warn you: you have a limit of 18 characters.
Also, we have
agvtool that can manage updates of both version & build number. To make it even more spicy, we have new terms as well as places where we can store this information:
- Marketing version for
CFBundleShortVersionString—aka Bundle version string, short—with a corresponding key
MARKETING_VERSIONin the project build settings.
- Current project version for
CFBundleVersion—aka Bundle version—with a corresponding key
CURRENT_PROJECT_VERSIONin the project build settings.
There is another article by Apple Technical Q&A QA1827: Automating Version and Build Numbers Using agvtool, which sort of limits our value choice in Current project version:
The value of
CURRENT_PROJECT_VERSIONmust be an integer or a floating point number such as 34.6.
And even if you decide to use a floating point number, there is another bummer with automatic increments:
agvtool next-version -allincrements your version number to the next highest integer value. For instance, it will update 2 to 3 and 1.3 to 2.
After reading all this, I've settled on using an integer number for
CFBundleVersion and don't store build metadata in this key (for release builds).
- It's easy to remember that in string, “short” is for Marketing Version.
- We can use only eighteen symbols in
CFBundleVersion, and this number reminds me of the lyrics from "I'm Eighteen" by Alice Cooper - 'Eighteen I get confused every day'.
CFBundleVersionshould be an integer number (or a floating point number).
- For macOS apps, both the build number & marketing version should be increased before release.