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

时间:2014-09-22 00:29:49

标签: ios swift

我有一个带有Azure后端的IOS应用,并希望记录某些事件,例如登录以及正在运行的应用用户的哪个版本。

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

34 个答案:

答案 0 :(得分:299)

修改

针对Swift 4.2进行了更新

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

修改

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

let nsObject: AnyObject? = NSBundle.mainBundle().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

我希望这可以帮助你。

大卫

答案 1 :(得分:263)

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

Swift 3.0:

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

Swift< 2.3

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

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

答案 2 :(得分:219)

针对Swift 3.0进行了更新

NS - 前缀现在已经在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

旧更新的答案

  

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

extension NSBundle {

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

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

}
     

现在,此扩展程序将在应用程序中用于识别主要内容   捆绑包和任何其他包含的捆绑包(例如共享框架)   扩展程序设计或第三个框架,如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"]
     

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

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

}
     

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

let versionNumber = NSBundle.applicationVersionNumber

答案 3 :(得分:62)

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

(*)更新了扩展名

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:旧答案

Swift 3.1

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

旧版本

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

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

self.labelVersion.text = getVersion()

答案 4 :(得分:29)

Swift 4.0

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

答案 5 :(得分:26)

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

}

然后使用它

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

答案 6 :(得分:16)

对于Swift 3.0,NSBundle无法正常工作,以下代码可以正常运行。

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

仅对于内部版本号,它是:

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

令人困惑的CFBundleVersion'是在X轴上输入的构建编号,在General-> Identity。

答案 7 :(得分:14)

Xcode 9.4.1 Swift 4.1

请注意使用localizedInfoDictionary来选择捆绑显示名称的正确语言版本。

Listbox

答案 8 :(得分:12)

Xcode 8,Swift 3:

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

答案 9 :(得分:11)

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

答案 10 :(得分:9)

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

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

答案 11 :(得分:9)

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 "⚠️"
        }
    }
}

SwiftUI示例使用

VStack {

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

答案 12 :(得分:8)

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

答案 13 :(得分:6)

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

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

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

答案 14 :(得分:6)

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

用法:

someLabel.text = Bundle.main.versionNumber

答案 15 :(得分:5)

对于Swift 1.2来说:

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIView *redView;

@property (strong, nonatomic) UITextField *textField;

@property (strong, nonatomic) UITapGestureRecognizer *gesture;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.textField                 = [[UITextField alloc] initWithFrame:CGRectMake(0.f, 0.f, self.redView.frame.size.width, 30.f)];
    self.textField.backgroundColor = [UIColor lightGrayColor];

    [self.redView addSubview:self.textField];

    self.gesture = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                           action:@selector(animateRedView:)];

    [self.view addGestureRecognizer:self.gesture];
}

- (IBAction)animateRedView:(id)sender
{
    [UIView animateWithDuration:.5
                          delay:0
         usingSpringWithDamping:1.2
          initialSpringVelocity:5
                        options:0
                     animations:^{

                         CGRect redViewFrame = self.redView.frame;

                         [self.redView setFrame:CGRectMake((self.view.frame.size.width - redViewFrame.size.width),
                                                           redViewFrame.origin.y,
                                                           redViewFrame.size.width,
                                                           redViewFrame.size.height)];

                     } completion:^(BOOL finished) {

                         [self.textField becomeFirstResponder];

                     }];
}

@end

答案 16 :(得分:4)

斯威夫特3:

版本号

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

内部版本号

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

答案 17 :(得分:3)

Swift 4

ref
  

Bundle.main.infoDictionary![" CFBundleShortVersionString"]

Swift旧语法

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

答案 18 :(得分:3)

对于 Swift 5

func getAppCurrentVersionNumber() -> String {
    let nsObject: AnyObject? = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as AnyObject?
    return nsObject as! String
}

答案 19 :(得分:2)

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

答案 20 :(得分: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
    }

}

注意: 如果你没有设置app版本或版本,你应该使用if here,如果你试图使用它会导致崩溃!打开包装。

答案 21 :(得分:1)

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

使用此库,读取应用程序版本和内部版本号将像这样简单:

import SwifterSwift

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

答案 22 :(得分:1)

SWIFT 4

//首先通过定义为可选的AnyObject

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

//然后将对象强制转换为String,但要小心,你可能需要仔细检查nil

let version = nsObject as! String

答案 23 :(得分:1)

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

答案 24 :(得分:1)

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

答案 25 :(得分:1)

我为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: " ")
    }
}

struct IdentifierConstants {
    struct InfoPlist {
        static let versionNumber = "CFBundleShortVersionString"
        static let buildNumber = "CFBundleVersion"
    }
}

答案 26 :(得分:0)

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

答案 27 :(得分:0)

简单的实用程序功能可将应用程序版本返回为 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
    }

答案 28 :(得分:0)

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

答案 29 :(得分:0)

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

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

答案 30 :(得分:0)

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。要不向新用户显示此屏幕,只需在首次登录后或入职完成后添加内部版本号即可。

答案 31 :(得分:0)

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

    }

答案 32 :(得分:-1)

对于 Swift 5.0

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

答案 33 :(得分:-1)

Swift 2.0

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

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