How can I programmatically get the value of the target version
, like in the image below?
As seen in the Properties window of the target of my Xcode proj
There are 2 Numbers!
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. It does not have to stop at 9, 1.11.23 is a reasonable version number.
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 or its commit number. This number should be unique to distinguish the different builds, which only have minor incremental changes.
Objective-C:
NSString * appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
Swift < 3.0:
let appVersionString: String = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
Swift 3.0+ (tested with 5.0):
let appVersionString: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
Objective-C:
NSString * appBuildString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
Swift < 3.0:
let buildNumber: String = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleVersion") as! String
Swift 3.0+ (tested until 5.0):
let buildNumber: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String
First use the above lines and then the following one.
Objective-C:
NSString * versionBuildString = [NSString stringWithFormat:@"Version: %@ (%@)", appVersionString, appBuildString];
Swift (tested until 5.0):
let versionAndBuildNumber: String = "\(appVersionString) (\(buildNumber))"
The values in the main bundle are not always present, for example in a command line application there is no CFBundleShortVersionString
or CFBundleVersion
, so the methods will return nil
and it will crash because in the code it makes a incorrect downcast.
But in normal Cocoa iOS and Mac apps these values are defined and will not be deleted.
This is tested with Xcode Version 7.3 (7D175). 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"
For Xcode
do the following:
I made an extension for Bundle so it will be easy to use
extension Bundle {
var releaseVersionNumber: String? {
return infoDictionary?["CFBundleShortVersionString"] as? String
}
var buildVersionNumber: String? {
return infoDictionary?["CFBundleVersion"] as? String
}
var applicationName: String {
return infoDictionary?["CFBundleDisplayName"] as? String ?? "ADKATech"
}
var applicationReleaseDate: String {
return infoDictionary?["ApplicationReleaseDate"] as? String ?? Date().description
}
var applicationReleaseNumber: Int {
return infoDictionary?["ApplicationReleaseNumber"] as? Int ?? 0
}
var releaseVersionNumberPretty: String {
return "\(releaseVersionNumber ?? "1.0.0")"
}
var buildVersionNumberPretty: String {
return "\(buildVersionNumber ?? "1")"
}
}
Here same code for Swift 3:
let versionNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
let buildNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String
Programmatically display version and build number - Swift 4.0
let versionNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "1.0"
let buildNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "1.0"
let versionAndBuildNumber = "Ver #\(versionNumber) ( Build #\(buildNumber) )"
You can also use like
var appVersion: String {
//versionNumber
let versionNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "1.0"
//buildNumber
let buildNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "1.0"
return "Version: #\(versionNumber) (#\(buildNumber))"
}
Then you can use anywhere when you declare Globally.
print(appVersion)
Output:
Version: #1.0 (#1.0.3)
You don't need to change anything in your project or Xcode. Here's the Swift version for both separately:
let versionNumber = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
let buildNumber = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleVersion") as! String
It's included in this repo, check it out:
https://github.com/goktugyil/EZSwiftExtensions