如何使用Swift获得应用程序版本和构建号?

时间:2023-02-01 07:16:50

I have an IOS app with an Azure back-end, and would like to log certain events, like logins and which versions of the app users are running.

我有一个具有Azure后端功能的IOS应用程序,我想记录一些事件,比如登录以及应用程序用户正在运行的哪个版本。

How can I return the version and build number using Swift?

如何使用Swift返回版本和构建数字?

19 个解决方案

#1


183  

EDIT

编辑

As pointed out by @azdev on the new version of Xcode you will get a compile error for trying my previous solution, to solve this just edit it as suggested to unwrap the bundle dictionary using a !

正如@azdev在新版本的Xcode中指出的那样,如果您尝试我以前的解决方案,您将会得到一个编译错误,要解决这个问题,只需按照建议使用a打开bundle dictionary即可!

let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]

End Edit

最后编辑

Just use the same logic than in Objective-C but with some small changes

使用与Objective-C相同的逻辑,但是有一些小的改变

//First get the nsObject by defining as an optional anyObject
let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary["CFBundleShortVersionString"]

//Then just cast the object as a String, but be careful, you may want to double check for nil
let version = nsObject as String

I hope this helps you out.

我希望这能帮助你。

David

大卫

#2


227  

I know this has already been answered but personally I think this is a little cleaner:

我知道这个问题已经得到了回答,但我个人认为这个问题更简洁了:

Swift 3.0:

斯威夫特3.0:

 if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
    self.labelVersion.text = version
}

Swift <2.3

斯威夫特< 2.3

if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
    self.labelVersion.text = version
}

This way, the if let version takes care of the conditional processing (setting the label text in my case) and if infoDictionary or CFBundleShortVersionString are nil the optional unwrapping will cause the code to be skipped.

这样,if let版本将处理条件处理(在我的例子中设置标签文本),如果infoDictionary或CFBundleShortVersionString是nil,可选的解包将导致代码被跳过。

#3


178  

Updated for Swift 3.0

3.0更新迅速

The NS-prefixes are now gone in Swift 3.0 and several properties/methods have changed names to be more Swifty. Here's what this looks like now:

ns -前缀现在已经在Swift 3.0中运行了,一些属性/方法已经更改了名称,使其更加灵活。这是现在的样子:

extension Bundle {
    var releaseVersionNumber: String? {
        return infoDictionary?["CFBundleShortVersionString"] as? String
    }
    var buildVersionNumber: String? {
        return infoDictionary?["CFBundleVersion"] as? String
    }
}

Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber

Old Updated Answer

旧更新答案

I've been working with Frameworks a lot since my original answer, so I wanted to update my solution to something that is both simpler and much more useful in a multi-bundle environment:

从我最初的答案开始,我就一直在使用框架,所以我想把我的解决方案更新为在多包环境中更简单、更有用的东西:

extension NSBundle {

    var releaseVersionNumber: String? {
        return self.infoDictionary?["CFBundleShortVersionString"] as? String
    }

    var buildVersionNumber: String? {
        return self.infoDictionary?["CFBundleVersion"] as? String
    }

}

Now this extension will be useful in apps to identify both the main bundle and any other included bundles (such as a shared framework for extension programming or third frameworks like AFNetworking), like so:

现在,这个扩展将在应用程序中很有用,可以识别主bundle和任何其他包含的bundle(比如用于扩展编程的共享框架或类似AFNetworking的第三方框架),如下所示:

NSBundle.mainBundle().releaseVersionNumber
NSBundle.mainBundle().buildVersionNumber

// or...

NSBundle(URL: someURL)?.releaseVersionNumber
NSBundle(URL: someURL)?.buildVersionNumber

Original Answer

原来的答案

I wanted to improve on some of the answers already posted. I wrote a class extension that can be added to your tool chain to handle this in a more logical fashion.

我想改进一些已经发布的答案。我编写了一个类扩展,可以添加到您的工具链中,以一种更符合逻辑的方式处理它。

extension NSBundle {

class var applicationVersionNumber: String {
    if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]

as? String { return version } return "Version Number Not Available" }

是吗?字符串{返回版本}返回“版本号不可用”}

class var applicationBuildNumber: String {
    if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String {
        return build
    }
    return "Build Number Not Available"
}

}

So now you can access this easily by:

所以现在你可以通过:

let versionNumber = NSBundle.applicationVersionNumber

#4


49  

I also know this has already been answered but I wrapped up the previous answers:

我也知道这个问题已经得到了回答,但我还是把之前的回答总结了一下:

Updated for extensions

extension Bundle {
    var releaseVersionNumber: String? {
        return infoDictionary?["CFBundleShortVersionString"] as? String
    }
    var buildVersionNumber: String? {
        return infoDictionary?["CFBundleVersion"] as? String
    }
    var releaseVersionNumberPretty: String {
        return "v\(releaseVersionNumber ?? "1.0.0")"
    }
}

Usage:

用法:

someLabel.text = Bundle.main.releaseVersionNumberPretty

Old answers

Updated for Swift 3.1:

更新迅速3.1:

class func getVersion() -> String {
    guard let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
        return "no version info"
    }
    return version
}

For older versions:

旧版本:

class func getVersion() -> String {
    if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
        return version
    }
    return "no version info"
}

So if you want to set label text or want to use somewhere else;

如果你想设置标签文本或者想在别的地方使用;

self.labelVersion.text = getVersion()

#5


22  

I made an Extension on Bundle

我在包裹上做了一个分机

extension Bundle {

    var appName: String {
        return infoDictionary?["CFBundleName"] as! String
    }

    var bundleId: String {
        return bundleIdentifier!
    }

    var versionNumber: String {
        return infoDictionary?["CFBundleShortVersionString"] as! String 
    }

    var buildNumber: String {
        return infoDictionary?["CFBundleVersion"] as! String
    }

}

and then use it

然后使用它

versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"

#6


16  

For Swift 3.0 NSBundle doesn't work, Following code works perfectly.

对于Swift 3.0 NSBundle,以下代码可以很好地工作。

let versionNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
          as! String

and for just the build number, it is:

仅仅是建造编号,它是:

let buildNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
          as! String

Confusingly 'CFBundleVersion' is the build number as entered in Xcode on General->Identity.

令人困惑的“CFBundleVersion”是在通用->标识上的Xcode中输入的构建号。

#7


16  

For Swift 4.0

斯威夫特4.0

let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!

#8


12  

Xcode 8, Swift 3:

斯威夫特Xcode 8日3:

let gAppVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let gAppBuild = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"

#9


9  

My answer (as at Aug 2015), given Swift keeps evolving:

我的答案(截至2015年8月),鉴于斯威夫特一直在进步:

let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String

#10


5  

For Swift 1.2 it's:

1.2快速的:

let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String

#11


5  

Having looked at the documentation, I believe that the following is cleaner:

看了文件后,我认为以下内容更清晰:

let version = 
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") 
as? String

Source: "Use of this method is preferred over other access methods because it returns the localized value of a key when one is available."

源:“与其他访问方法相比,首选使用此方法,因为它在可用时返回键的本地化值。”

#12


4  

Swift 3:

斯威夫特3:

Version Number

版本号

if let versionNumberString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { // do something }

Build number

建立数

if let buildNumberString = Bundle.main.infoDictionary?["CFBundleVersion"] as? String { // do something }

#13


2  

extension UIApplication {

    static var appVersion: String {
        if let appVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") {
            return "\(appVersion)"
        } else {
            return ""
        }
    }

    static var build: String {
        if let buildVersion = NSBundle.mainBundle().objectForInfoDictionaryKey(kCFBundleVersionKey as String) {
            return "\(buildVersion)"
        } else {
            return ""
        }
    }

    static var versionBuild: String {
        let version = UIApplication.appVersion
        let build = UIApplication.build

        var versionAndBuild = "v\(version)"

        if version != build {
            versionAndBuild = "v\(version)(\(build))"
        }

        return versionAndBuild
    }

}

Attention: You should use if let here in case that the app version or build is not set which will lead to crash if you try to use ! to unwrap.

注意:如果没有设置应用程序版本或构建,您应该在这里使用if,如果您试图使用它,它将导致崩溃!打开。

#14


2  

public var appVersionNumberString: String {
get {
    return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
}
}

#15


2  

Swift 4

斯威夫特4

func getAppVersion() -> String {
    return "\(Bundle.main.infoDictionary!["CFBundleShortVersionString"] ?? "")"
}

Bundle.main.infoDictionary!["CFBundleShortVersionString"]

Bundle.main.infoDictionary !(“CFBundleShortVersionString”)

Swift old syntax

斯威夫特旧语法

let appVer: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]

#16


1  

Here's an updated version for Swift 3.2:

以下是Swift 3.2的更新版本:

extension UIApplication
{
    static var appVersion:String
    {
        if let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
        {
            return "\(appVersion)"
        }
        return ""
    }

    static var buildNumber:String
    {
        if let buildNum = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String)
        {
            return "\(buildNum)"
        }
        return ""
    }

    static var versionString:String
    {
        return "\(appVersion).\(buildNumber)"
    }
}

#17


1  

SWIFT 4

斯威夫特4

//First get the nsObject by defining as an optional AnyObject

//首先通过定义为可选的AnyObject来获得nsObject

let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject

//Then just cast the object as a String, but be careful, you may want to double check for nil

//然后将对象转换为字符串,但是要小心,您可能需要再次检查nil

let version = nsObject as! String

#18


0  

Xcode 9.3.1 Swift 4.2

Xcode 4.2设备上装迅速

var version: String?
var build: String?

override func viewDidLoad() {
    super.viewDidLoad()

    // Get version and build
    if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
        self.version = version
    }
    if let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
        self.build = build
    }
}

#19


-1  

For Swift 2.0

斯威夫特2.0

//First get the nsObject by defining as an optional anyObject

let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]
let version = nsObject as! String

#1


183  

EDIT

编辑

As pointed out by @azdev on the new version of Xcode you will get a compile error for trying my previous solution, to solve this just edit it as suggested to unwrap the bundle dictionary using a !

正如@azdev在新版本的Xcode中指出的那样,如果您尝试我以前的解决方案,您将会得到一个编译错误,要解决这个问题,只需按照建议使用a打开bundle dictionary即可!

let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]

End Edit

最后编辑

Just use the same logic than in Objective-C but with some small changes

使用与Objective-C相同的逻辑,但是有一些小的改变

//First get the nsObject by defining as an optional anyObject
let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary["CFBundleShortVersionString"]

//Then just cast the object as a String, but be careful, you may want to double check for nil
let version = nsObject as String

I hope this helps you out.

我希望这能帮助你。

David

大卫

#2


227  

I know this has already been answered but personally I think this is a little cleaner:

我知道这个问题已经得到了回答,但我个人认为这个问题更简洁了:

Swift 3.0:

斯威夫特3.0:

 if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
    self.labelVersion.text = version
}

Swift <2.3

斯威夫特< 2.3

if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
    self.labelVersion.text = version
}

This way, the if let version takes care of the conditional processing (setting the label text in my case) and if infoDictionary or CFBundleShortVersionString are nil the optional unwrapping will cause the code to be skipped.

这样,if let版本将处理条件处理(在我的例子中设置标签文本),如果infoDictionary或CFBundleShortVersionString是nil,可选的解包将导致代码被跳过。

#3


178  

Updated for Swift 3.0

3.0更新迅速

The NS-prefixes are now gone in Swift 3.0 and several properties/methods have changed names to be more Swifty. Here's what this looks like now:

ns -前缀现在已经在Swift 3.0中运行了,一些属性/方法已经更改了名称,使其更加灵活。这是现在的样子:

extension Bundle {
    var releaseVersionNumber: String? {
        return infoDictionary?["CFBundleShortVersionString"] as? String
    }
    var buildVersionNumber: String? {
        return infoDictionary?["CFBundleVersion"] as? String
    }
}

Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber

Old Updated Answer

旧更新答案

I've been working with Frameworks a lot since my original answer, so I wanted to update my solution to something that is both simpler and much more useful in a multi-bundle environment:

从我最初的答案开始,我就一直在使用框架,所以我想把我的解决方案更新为在多包环境中更简单、更有用的东西:

extension NSBundle {

    var releaseVersionNumber: String? {
        return self.infoDictionary?["CFBundleShortVersionString"] as? String
    }

    var buildVersionNumber: String? {
        return self.infoDictionary?["CFBundleVersion"] as? String
    }

}

Now this extension will be useful in apps to identify both the main bundle and any other included bundles (such as a shared framework for extension programming or third frameworks like AFNetworking), like so:

现在,这个扩展将在应用程序中很有用,可以识别主bundle和任何其他包含的bundle(比如用于扩展编程的共享框架或类似AFNetworking的第三方框架),如下所示:

NSBundle.mainBundle().releaseVersionNumber
NSBundle.mainBundle().buildVersionNumber

// or...

NSBundle(URL: someURL)?.releaseVersionNumber
NSBundle(URL: someURL)?.buildVersionNumber

Original Answer

原来的答案

I wanted to improve on some of the answers already posted. I wrote a class extension that can be added to your tool chain to handle this in a more logical fashion.

我想改进一些已经发布的答案。我编写了一个类扩展,可以添加到您的工具链中,以一种更符合逻辑的方式处理它。

extension NSBundle {

class var applicationVersionNumber: String {
    if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]

as? String { return version } return "Version Number Not Available" }

是吗?字符串{返回版本}返回“版本号不可用”}

class var applicationBuildNumber: String {
    if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String {
        return build
    }
    return "Build Number Not Available"
}

}

So now you can access this easily by:

所以现在你可以通过:

let versionNumber = NSBundle.applicationVersionNumber

#4


49  

I also know this has already been answered but I wrapped up the previous answers:

我也知道这个问题已经得到了回答,但我还是把之前的回答总结了一下:

Updated for extensions

extension Bundle {
    var releaseVersionNumber: String? {
        return infoDictionary?["CFBundleShortVersionString"] as? String
    }
    var buildVersionNumber: String? {
        return infoDictionary?["CFBundleVersion"] as? String
    }
    var releaseVersionNumberPretty: String {
        return "v\(releaseVersionNumber ?? "1.0.0")"
    }
}

Usage:

用法:

someLabel.text = Bundle.main.releaseVersionNumberPretty

Old answers

Updated for Swift 3.1:

更新迅速3.1:

class func getVersion() -> String {
    guard let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
        return "no version info"
    }
    return version
}

For older versions:

旧版本:

class func getVersion() -> String {
    if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
        return version
    }
    return "no version info"
}

So if you want to set label text or want to use somewhere else;

如果你想设置标签文本或者想在别的地方使用;

self.labelVersion.text = getVersion()

#5


22  

I made an Extension on Bundle

我在包裹上做了一个分机

extension Bundle {

    var appName: String {
        return infoDictionary?["CFBundleName"] as! String
    }

    var bundleId: String {
        return bundleIdentifier!
    }

    var versionNumber: String {
        return infoDictionary?["CFBundleShortVersionString"] as! String 
    }

    var buildNumber: String {
        return infoDictionary?["CFBundleVersion"] as! String
    }

}

and then use it

然后使用它

versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"

#6


16  

For Swift 3.0 NSBundle doesn't work, Following code works perfectly.

对于Swift 3.0 NSBundle,以下代码可以很好地工作。

let versionNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
          as! String

and for just the build number, it is:

仅仅是建造编号,它是:

let buildNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
          as! String

Confusingly 'CFBundleVersion' is the build number as entered in Xcode on General->Identity.

令人困惑的“CFBundleVersion”是在通用->标识上的Xcode中输入的构建号。

#7


16  

For Swift 4.0

斯威夫特4.0

let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!

#8


12  

Xcode 8, Swift 3:

斯威夫特Xcode 8日3:

let gAppVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let gAppBuild = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"

#9


9  

My answer (as at Aug 2015), given Swift keeps evolving:

我的答案(截至2015年8月),鉴于斯威夫特一直在进步:

let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String

#10


5  

For Swift 1.2 it's:

1.2快速的:

let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String

#11


5  

Having looked at the documentation, I believe that the following is cleaner:

看了文件后,我认为以下内容更清晰:

let version = 
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") 
as? String

Source: "Use of this method is preferred over other access methods because it returns the localized value of a key when one is available."

源:“与其他访问方法相比,首选使用此方法,因为它在可用时返回键的本地化值。”

#12


4  

Swift 3:

斯威夫特3:

Version Number

版本号

if let versionNumberString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { // do something }

Build number

建立数

if let buildNumberString = Bundle.main.infoDictionary?["CFBundleVersion"] as? String { // do something }

#13


2  

extension UIApplication {

    static var appVersion: String {
        if let appVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") {
            return "\(appVersion)"
        } else {
            return ""
        }
    }

    static var build: String {
        if let buildVersion = NSBundle.mainBundle().objectForInfoDictionaryKey(kCFBundleVersionKey as String) {
            return "\(buildVersion)"
        } else {
            return ""
        }
    }

    static var versionBuild: String {
        let version = UIApplication.appVersion
        let build = UIApplication.build

        var versionAndBuild = "v\(version)"

        if version != build {
            versionAndBuild = "v\(version)(\(build))"
        }

        return versionAndBuild
    }

}

Attention: You should use if let here in case that the app version or build is not set which will lead to crash if you try to use ! to unwrap.

注意:如果没有设置应用程序版本或构建,您应该在这里使用if,如果您试图使用它,它将导致崩溃!打开。

#14


2  

public var appVersionNumberString: String {
get {
    return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
}
}

#15


2  

Swift 4

斯威夫特4

func getAppVersion() -> String {
    return "\(Bundle.main.infoDictionary!["CFBundleShortVersionString"] ?? "")"
}

Bundle.main.infoDictionary!["CFBundleShortVersionString"]

Bundle.main.infoDictionary !(“CFBundleShortVersionString”)

Swift old syntax

斯威夫特旧语法

let appVer: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]

#16


1  

Here's an updated version for Swift 3.2:

以下是Swift 3.2的更新版本:

extension UIApplication
{
    static var appVersion:String
    {
        if let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
        {
            return "\(appVersion)"
        }
        return ""
    }

    static var buildNumber:String
    {
        if let buildNum = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String)
        {
            return "\(buildNum)"
        }
        return ""
    }

    static var versionString:String
    {
        return "\(appVersion).\(buildNumber)"
    }
}

#17


1  

SWIFT 4

斯威夫特4

//First get the nsObject by defining as an optional AnyObject

//首先通过定义为可选的AnyObject来获得nsObject

let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject

//Then just cast the object as a String, but be careful, you may want to double check for nil

//然后将对象转换为字符串,但是要小心,您可能需要再次检查nil

let version = nsObject as! String

#18


0  

Xcode 9.3.1 Swift 4.2

Xcode 4.2设备上装迅速

var version: String?
var build: String?

override func viewDidLoad() {
    super.viewDidLoad()

    // Get version and build
    if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
        self.version = version
    }
    if let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
        self.build = build
    }
}

#19


-1  

For Swift 2.0

斯威夫特2.0

//First get the nsObject by defining as an optional anyObject

let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]
let version = nsObject as! String