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

我有一个带有Azure后端的IOS应用程序,想要记录某些事件,如登录和应用程序用户正在运行的版本。

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

253218 次浏览

编辑

Swift 4.2更新

let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String

编辑

正如@azdev在Xcode的新版本上指出的那样,你会得到一个编译错误,尝试我以前的解决方案,要解决这个问题,只需编辑它,建议使用一个打开包字典!

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

最后编辑

使用与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

我知道这个问题已经有人回答了,但我个人认为这个问题更清晰一些:

斯威夫特3.0:

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

斯威夫特& lt; 2.3

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

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

我也知道这个问题已经有了答案,但我总结了之前的答案:

(*)扩展更新

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")"
}
}

用法:

someLabel.text = Bundle.main.releaseVersionNumberPretty

@Deprecated:旧答案

# EYZ0:

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

# EYZ0:

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

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

self.labelVersion.text = getVersion()

针对Swift 3.0更新

# eyz0前缀现在在Swift 3.0中消失了,一些属性/方法的名称已经更改为更Swifty。这是现在的样子:

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


Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber

# EYZ0

自从我最初的答案以来,我一直在使用框架工作,所以我 我想更新我的解决方案,使之更简单 在多包环境中更有用:

extension NSBundle {


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


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


}

现在这个扩展将是有用的应用程序来识别两个主要的 Bundle和任何其他包含的Bundle(例如 扩展编程或AFNetworking等第三方框架),如下:

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


// or...


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

原来的答案

我想改进已经发布的一些答案。我写了 类扩展,可以添加到您的工具链中处理此问题

extension NSBundle {


class var applicationVersionNumber: String {
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]
< p > ?字符串{ 返回的版本 } 返回“版本号不可用” } < / p >
class var applicationBuildNumber: String {
if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String {
return build
}
return "Build Number Not Available"
}


}

所以现在你可以通过以下方式轻松访问:

let versionNumber = NSBundle.applicationVersionNumber

对于Swift 1.2,它是:

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

鉴于Swift一直在发展,我的回答(截至2015年8月):

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

为# EYZ0

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


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

看过文档后,我认为以下内容更清晰:

let version =
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString")
as? String
< p > # EYZ0: 使用此方法优于其他访问方法,因为它在键可用时返回键的本地化值。< / p >
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
}


}
< p >注意: 你应该在这里使用if,以防应用程序版本或构建没有设置,这将导致崩溃,如果你尝试使用!打开。< / p >

斯威夫特3:

版本号

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

建立数

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

Xcode 8, Swift 3:

let gAppVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let gAppBuild = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"
public var appVersionNumberString: String {
get {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
}
}

我在捆绑上做了一个扩展

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
}


}

然后使用它

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

对于Swift 3.0 NSBundle不工作,下面的代码工作完美。

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

对于版本号,它是:

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

令人困惑的是,'CFBundleVersion'是在Xcode中输入的构建号码,在General->身份。

以下是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)"
}
}

斯威夫特4

//首先通过定义一个可选的AnyObject来获取nsObject

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

//然后将对象转换为String,但要小心,你可能需要再次检查是否为nil

let version = nsObject as! String

斯威夫特4

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

Bundle.main.infoDictionary ![" CFBundleShortVersionString "]

快速旧语法

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

为# EYZ0

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

Xcode 9.4.1 Swift 4.1

注意,使用localizedInfoDictionary来获取包显示名称的正确语言版本。

var displayName: String?
var version: String?
var build: String?


override func viewDidLoad() {
super.viewDidLoad()


// Get display name, version and build


if let displayName = Bundle.main.localizedInfoDictionary?["CFBundleDisplayName"] as? String {
self.displayName = displayName
}
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.version = version
}
if let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
self.build = build
}
}

对于任何感兴趣的人,在github上有一个漂亮而整洁的库,名为SwifterSwift,它也为每个版本的swift提供了完整的文档(参见swifterswift.com)。

使用这个库,读取应用版本和构建号就像这样简单:

import SwifterSwift


let buildNumber = SwifterSwift.appBuild
let version = SwifterSwift.appVersion

Swift 4,有用的扩展包

import Foundation


public extension Bundle {


public var shortVersion: String {
if let result = infoDictionary?["CFBundleShortVersionString"] as? String {
return result
} else {
assert(false)
return ""
}
}


public var buildVersion: String {
if let result = infoDictionary?["CFBundleVersion"] as? String {
return result
} else {
assert(false)
return ""
}
}


public var fullVersion: String {
return "\(shortVersion)(\(buildVersion))"
}
}

包+ Extensions.swift

import Foundation


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


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


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

用法:

someLabel.text = Bundle.main.versionNumber
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
lblVersion.text = "Version \(version)"


}

Swift 5更新

这里有一个函数,我使用它来决定是否显示“应用程序更新”;呼不呼。它返回版本号,我正在将其转换为Int类型:

if let version: String = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
guard let intVersion = Int(version) else { return }
        

if UserDefaults.standard.integer(forKey: "lastVersion") < intVersion {
print("need to show popup")
} else {
print("Don't need to show popup")
}
        

UserDefaults.standard.set(intVersion, forKey: "lastVersion")
}

如果以前从未使用过,它将返回0,小于当前版本号。若要不向新用户显示这样的屏幕,只需在首次登录后或登录完成时添加构建号。

现在您可以使用常量来实现这一点,而不必像以前那样使用字符串类型的代码,这使得事情变得更加方便。

var appVersion: String {
return Bundle.main.infoDictionary![kCFBundleVersionKey as String] as! String
}

OP同时要求版本号和版本号。不幸的是,大多数答案都不提供这两个选项。另外,还有一些添加了不必要的扩展方法。这里有一个非常简单的方法,可以解决OP的问题:

// Example output: "1.0 (234)"
private func versionAndBuildNumber() -> String {
let versionNumber = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
if let versionNumber = versionNumber, let buildNumber = buildNumber {
return "\(versionNumber) (\(buildNumber))"
} else if let versionNumber = versionNumber {
return versionNumber
} else if let buildNumber = buildNumber {
return buildNumber
} else {
return ""
}
}

对于斯威夫特5.0:

let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String

简单的实用程序函数返回应用程序版本为Int

func getAppVersion() -> Int {


if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {


let appVersionClean = appVersion.replacingOccurrences(of: ".", with: "", options: NSString.CompareOptions.literal, range:nil)


if let appVersionNum = Int(appVersionClean) {
return appVersionNum
}
}
return 0
}

我为UIApplication创建了一个扩展。

extension UIApplication {
static var appVersion: String {
let versionNumber = Bundle.main.infoDictionary?[IdentifierConstants.InfoPlist.versionNumber] as? String
let buildNumber = Bundle.main.infoDictionary?[IdentifierConstants.InfoPlist.buildNumber] as? String
        

let formattedBuildNumber = buildNumber.map {
return "(\($0))"
}


return [versionNumber,formattedBuildNumber].compactMap { $0 }.joined(separator: " ")
}
}


enum Constants {
enum InfoPlist {
static let versionNumber = "CFBundleShortVersionString"
static let buildNumber = "CFBundleVersion"
}
}
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.lblAppVersionValue.text = version
}

Swift 5作为UIApplication扩展

extension UIApplication {
static var release: String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String? ?? "x.x"
}
static var build: String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String? ?? "x"
}
static var version: String {
return "\(release).\(build)"
}
}

使用示例:

print("release: \(UIApplication.release)")
print("build: \(UIApplication.build)")
print("version: \(UIApplication.version)")

捆绑+扩展. Swift (SwiftUI, Swift 5, Xcode 11)

我结合了一些答案的想法,并扩展了一点:

  • 一个SwiftUI的例子
  • 如果Info.plist中缺少键,则显示警告三角形表情符号(而不是使应用程序崩溃)

进口的基础

extension Bundle {
    

public var appVersionShort: String {
if let result = infoDictionary?["CFBundleShortVersionString"] as? String {
return result
} else {
return "⚠️"
}
}
public var appVersionLong: String {
if let result = infoDictionary?["CFBundleVersion"] as? String {
return result
} else {
return "⚠️"
}
}
public var appName: String {
if let result = infoDictionary?["CFBundleName"] as? String {
return result
} else {
return "⚠️"
}
}
}

SwiftUI实例使用

VStack {


Text("Version: \(Bundle.main.appVersionShort!) (\(Bundle.main.appVersionLong!))")
.font(.subheadline)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}

斯威夫特5.3

let infoDictionaryKey = kCFBundleVersionKey as String
guard let currentVersion = Bundle.main.object(forInfoDictionaryKey: infoDictionaryKey) as? String
else { fatalError("Expected to find a bundle version in the info dictionary") }

2022年,Swift 5

extension Bundle {
public var appName: String { getInfo("CFBundleName")  }
public var displayName: String {getInfo("CFBundleDisplayName")}
public var language: String {getInfo("CFBundleDevelopmentRegion")}
public var identifier: String {getInfo("CFBundleIdentifier")}
public var copyright: String {getInfo("NSHumanReadableCopyright").replacingOccurrences(of: "\\\\n", with: "\n") }
    

public var appBuild: String { getInfo("CFBundleVersion") }
public var appVersionLong: String { getInfo("CFBundleShortVersionString") }
//public var appVersionShort: String { getInfo("CFBundleShortVersion") }
    

fileprivate func getInfo(_ str: String) -> String { infoDictionary?[str] as? String ?? "⚠️" }
}

用法(SwiftUI样本):

    Text("Ver: \(Bundle.main.appVersionLong) (\(Bundle.main.appBuild)) ")
    

Text(Bundle.main.copyright)
.font(.system(size: 10, weight: .thin))
.multilineTextAlignment(.center)

奖励:版权支持\n符号!

enter image description here