如何使用Swift获取App版本和内部版本号?

Øyv*_*Vik 352 ios swift

我有一个带有Azure后端的IOS应用程序,并且想要记录某些事件,例如登录以及正在运行的应用程序用户的哪个版本.

如何使用Swift返回版本和内部版本号?

Dav*_*vid 363

编辑

针对Swift 4.2进行了更新

let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
Run Code Online (Sandbox Code Playgroud)

编辑

正如@azdev在Xcode的新版本中所指出的那样,你会在尝试我之前的解决方案时遇到编译错误,解决这个问题只需按照建议编辑它就可以使用!来解开捆绑字典!

let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]
Run Code Online (Sandbox Code Playgroud)

结束编辑

只需使用与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
Run Code Online (Sandbox Code Playgroud)

我希望这能够帮到你.

大卫

  • @andreas`infoDictionary`应该用`!`解包.这就是我正在使用的,放在Globals.swift文件中:`let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as String` (17认同)
  • 我很困惑。这只是内部版本号,对吗?应用程序版本怎么样? (3认同)
  • 您应该避免使用强制展开“!” 因为只要这些值之一为零,它们就会导致您的应用程序崩溃 (3认同)
  • 我不得不再加一个“!” 在“作为”之后。`let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! 字符串` (2认同)
  • @Julius我认为当这些值之一为空时应用程序应该崩溃 - 你还要做什么? (2认同)

小智 272

我知道这已经得到了解答,但我个人认为这有点清洁:

Swift 3.0:

 if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
    self.labelVersion.text = version
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特<2.3

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

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

  • 有没有理由不设置价值?同意它对'let`肯定更加谨慎,只是想知道为什么可能需要它.谢谢! (6认同)
  • ```self.labelVersion.text```是可选类型,所以你可以直接指定```NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]?String``` (5认同)

Bla*_*man 236

更新了Swift 3.0

NS现在-prefixes都走了斯威夫特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
Run Code Online (Sandbox Code Playgroud)

旧更新的答案

自从我的原始答案以来,我一直在使用Frameworks,所以我想将我的解决方案更新为更简单且在多捆绑环境中更有用的东西:

extension NSBundle {

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

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

}
Run Code Online (Sandbox Code Playgroud)

现在,这个扩展将在应用程序中用于识别主包和任何其他包含的包(例如扩展编程的共享框架或AFNetworking等第三个框架),如下所示:

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

// or...

NSBundle(URL: someURL)?.releaseVersionNumber
NSBundle(URL: someURL)?.buildVersionNumber
Run Code Online (Sandbox Code Playgroud)

原始答案

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

extension NSBundle {

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

如?String {return version}返回"版本号不可用"}

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

}
Run Code Online (Sandbox Code Playgroud)

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

let versionNumber = NSBundle.applicationVersionNumber
Run Code Online (Sandbox Code Playgroud)


And*_*rew 88

2023,斯威夫特 3-\xe2\x88\x9e

\n
extension Bundle {\n    public var appName: String           { getInfo("CFBundleName") }\n    public var displayName: String       { getInfo("CFBundleDisplayName") }\n    public var language: String          { getInfo("CFBundleDevelopmentRegion") }\n    public var identifier: String        { getInfo("CFBundleIdentifier") }\n    public var copyright: String         { getInfo("NSHumanReadableCopyright").replacingOccurrences(of: "\\\\\\\\n", with: "\\n") }\n    \n    public var appBuild: String          { getInfo("CFBundleVersion") }\n    public var appVersionLong: String    { getInfo("CFBundleShortVersionString") }\n    //public var appVersionShort: String { getInfo("CFBundleShortVersion") }\n    \n    fileprivate func getInfo(_ str: String) -> String { infoDictionary?[str] as? String ?? "\xe2\x9a\xa0\xef\xb8\x8f" }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

用法(SwiftUI 示例):

\n
Text("Ver: \\(Bundle.main.appVersionLong) (\\(Bundle.main.appBuild)) ")\n\nText(Bundle.main.copyright)\n    .font(.system(size: 10, weight: .thin))\n    .multilineTextAlignment(.center)\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

在此输入图像描述

\n


Gun*_*han 66

我也知道这已经得到了解答,但我结束了以前的答案:

(*)更新了扩展名

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")"
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

someLabel.text = Bundle.main.releaseVersionNumberPretty
Run Code Online (Sandbox Code Playgroud)

@Deprecated:老答案

Swift 3.1:

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

对于旧版本:

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

因此,如果您想设置标签文本或想要在其他地方使用;

self.labelVersion.text = getVersion()
Run Code Online (Sandbox Code Playgroud)


小智 30

对于Swift 4.0

let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!
Run Code Online (Sandbox Code Playgroud)


car*_*ich 29

我在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
    }

}
Run Code Online (Sandbox Code Playgroud)

然后使用它

versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"
Run Code Online (Sandbox Code Playgroud)


jef*_*igy 26

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)"
    }
}
Run Code Online (Sandbox Code Playgroud)

示例使用:

print("release: \(UIApplication.release)")
print("build: \(UIApplication.build)")
print("version: \(UIApplication.version)")
Run Code Online (Sandbox Code Playgroud)


小智 20

Bundle+Extension.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 "??"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

SwiftUI 示例使用

VStack {

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

  • 我认为没有必要在 Bundle 扩展方法中返回可选字符串;常规的也可以与后备一起使用。 (4认同)

Seb*_*ldt 17

我为 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"
    }
}
Run Code Online (Sandbox Code Playgroud)


Tej*_*jas 16

对于Swift 3.0,NSBundle不起作用,以下代码完美运行.

let versionNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
          as! String
Run Code Online (Sandbox Code Playgroud)

而对于构建号,它是:

let buildNumberString =
      Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
          as! String
Run Code Online (Sandbox Code Playgroud)

令人困惑的'CFBundleVersion'是在General-> Identity上的Xcode中输入的内部版本号.


Hug*_*o F 15

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
    }
}
Run Code Online (Sandbox Code Playgroud)


Cra*_*lot 14

Xcode 8,Swift 3:

let gAppVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let gAppBuild = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"
Run Code Online (Sandbox Code Playgroud)


mas*_*vsa 11

Swift 4,Bundle的有用扩展

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))"
    }
}
Run Code Online (Sandbox Code Playgroud)


Cha*_*man 9

我的回答(截至2015年8月),鉴于Swift不断发展:

let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Run Code Online (Sandbox Code Playgroud)


Gia*_*ang 8

Bundle + 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
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

someLabel.text = Bundle.main.versionNumber
Run Code Online (Sandbox Code Playgroud)


Ora*_*chi 7

斯威夫特 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") }
Run Code Online (Sandbox Code Playgroud)


小智 6

看了一下文档后,我相信以下内容更清晰:

let version = 
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") 
as? String
Run Code Online (Sandbox Code Playgroud)

来源:"使用此方法优先于其他访问方法,因为它在一个可用时返回键的本地化值."


Sen*_*ful 6

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 ""
  }
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*lov 5

对于Swift 1.2,它是:

let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Run Code Online (Sandbox Code Playgroud)


小智 5

对于Swift 5.0

let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
Run Code Online (Sandbox Code Playgroud)