I have an app that I developed with Xcode 3 and recently started editing with Xcode 4. In the target summary I have the iOS application target form with fields: identifier, version, build, devices, and deployment target. The version field is blank and the build field is 3.4.0 (which matches the version of the app from when I was still editing with Xcode 3).
My questions are:
What is the difference between the version and build fields?
Why was the version field blank after I upgraded to Xcode 4?
(Just leaving this here for my own reference.) This will show version and build for the "version" and "build" fields you see in an Xcode target:
- (NSString*) version {
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
return [NSString stringWithFormat:@"%@ build %@", version, build];
}
In Swift
func version() -> String {
let dictionary = NSBundle.mainBundle().infoDictionary!
let version = dictionary["CFBundleShortVersionString"] as? String
let build = dictionary["CFBundleVersion"] as? String
return "\(version) build \(build)"
}
Another way is to set the version number in appDelegate
didFinishLaunchingWithOptions
:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString * ver = [self myVersion];
NSLog(@"version: %@",ver);
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:ver forKey:@"version"];
return YES;
}
- (NSString *) myVersion {
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
return [NSString stringWithFormat:@"%@ build %@", version, build];
}
Thanks to @nekno and @ale84 for great answers.
However, I modified @ale84's script it little to increment build numbers for floating point.
the value of incl can be changed according to your floating format requirements. For eg: if incl = .01, output format would be ... 1.19, 1.20, 1.21 ...
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
incl=.01
buildNumber=`echo $buildNumber + $incl|bc`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
The script to autoincrement the build number in the answer above didn't work for me if the build number is a floating point value, so I modified it a little:
#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=`echo $buildNumber +1|bc`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
The Build number is an internal number that indicates the current state of the app. It differs from the Version number in that it's typically not user facing and doesn't denote any difference/features/upgrades like a version number typically would.
Think of it like this:
CFBundleVersion
): The number of the build. Usually you start this at 1 and increase by 1 with each build of the app. It quickly allows for comparisons of which build is more recent and it denotes the sense of progress of the codebase. These can be overwhelmingly valuable when working with QA and needing to be sure bugs are logged against the right builds.CFBundleShortVersionString
): The user-facing number you are using to denote this version of your app. Usually this follows a Major.minor version scheme (e.g. MyAwesomeApp 1.2) to let users know which releases are smaller maintenance updates and which are big deal new features.To use this effectively in your projects, Apple provides a great tool called agvtool
. I highly recommend using this as it is MUCH more simple than scripting up plist changes. It allows you to easily set both the build number and the marketing version. It is particularly useful when scripting (for instance, easily updating the build number on each build or even querying what the current build number is). It can even do more exotic things like tag your SVN for you when you update the build number.
To use it:
agvtool new-version 1
(set the Build number to 1)agvtool new-marketing-version 1.0
(set the Marketing version to 1.0)See the man page of agvtool
for a ton of good info
The marketing release number is for the customers, called version number. It starts with 1.0 and goes up for major updates to 2.0, 3.0, for minor updates to 1.1, 1.2 and for bug fixes to 1.0.1, 1.0.2 . This number is oriented about releases and new features.
The build number is mostly the internal number of builds that have been made until then. But some use other numbers like the branch number of the repository. This number should be unique to distinguish the different nearly the same builds.
As you can see, the build number is not necessary and it is up to you which build number you want to use. So if you update your Xcode
to a major version, the build field is empty. The version field may not be empty!.
To get the build number as a NSString
variable:
NSString * appBuildString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
To get the version number as a NSString
variable:
NSString * appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
If you want both in one NSString
:
NSString * versionBuildString = [NSString stringWithFormat:@"Version: %@ (%@)", appVersionString, appBuildString];
This is tested with Xcode Version 4.6.3 (4H1503). The build number is often written in parenthesis / braces. The build number is in hexadecimal or decimal.
In Xcode you can auto-increment the build number as a decimal number by placing the following in the Run script
build phase in the project settings
#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
For hexadecimal build number use this script
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$((0x$buildNumber))
buildNumber=$(($buildNumber + 1))
buildNumber=$(printf "%X" $buildNumber)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
Source: Stackoverflow.com