使用Swift获取版本和构建信息

113

我正在尝试访问主要的NSBundle以检索版本构建信息。问题是,我想在Swift中尝试它,我知道如何在Objective-C中检索:

text = [NSBundle.mainBundle.infoDictionary objectForKey:@"CFBundleVersion"];

我不知道从哪里开始学习Swift,我尝试使用新的语法编写它,但没有成功。


2
展示你已经尝试过的内容。这与Objective-C的实现非常相似。 - Mick MacCallum
2017年1月 Swift 2.3: let sVer = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String let sBuild = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String self.myVersionLabel.text = String(format: "版本 %@ 构建 %@", sVer!, sBuild!) - Matthew Ferguson
17个回答

185

Swift语法有什么问题?这个似乎可以解决:

if let text = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
    print(text)
}

3
为什么这个被踩了?我猜用 let 更自然一些,但它看起来是正确的。 - Tommy
啊,我忘记加上“as String”了,所以变量无法接受它作为字符串。谢谢。 - Ken-UbiDex
3
似乎在XCode 6测试版3中出了问题。 - Frederic Adda
2
这段代码在 Xcode 6 beta 5 中对我有效:let text = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]! as String - E. Barnes
@Dean 看起来他们将infoDictionary更改为返回可选项。我已经编辑了答案。 - Connor
显示剩余2条评论

134

Swift 3/4 版本

func version() -> String {
    let dictionary = Bundle.main.infoDictionary!
    let version = dictionary["CFBundleShortVersionString"] as! String
    let build = dictionary["CFBundleVersion"] as! String
    return "\(version) build \(build)"
} 

Swift 2.x 版本

func version() -> String {
    let dictionary = NSBundle.mainBundle().infoDictionary!
    let version = dictionary["CFBundleShortVersionString"] as String
    let build = dictionary["CFBundleVersion"] as String
    return "\(version) build \(build)"
}

可以在这里看到。


1
您获取了相同的密钥两次,应该使用“CFBundleVersion”来表示版本。我猜这是复制/粘贴时的笔误 :) - foOg
谢谢@foOg,那是个笔误。实际上相反:短的是版本,常规的是构建。很奇怪,我知道。 - Dan Rosenstark
Swift 3 版本。如果 let infoPath = Bundle.main.path(forResource: "Info.plist", ofType: nil), let infoAttr = try? FileManager.default.attributesOfItem(atPath: infoPath), let infoDate = infoAttr[.creationDate] as? Date { return infoDate } return Date() - Ryan X

27

关于 Swift 5.0

我创建了一个包装器,将所有我的应用程序中的一些与应用相关的字符串集中在一个地方,称为AppInfo

/// Wrapper to get some app related strings at one place.
struct AppInfo {

   /// Returns the official app name, defined in your project data.
   var appName : String {
       return readFromInfoPlist(withKey: "CFBundleName") ?? "(unknown app name)"
   }

   /// Return the official app display name, eventually defined in your 'infoplist'.
   var displayName : String {
       return readFromInfoPlist(withKey: "CFBundleDisplayName") ?? "(unknown app display name)"
   }

   /// Returns the official version, defined in your project data.
   var version : String {
       return readFromInfoPlist(withKey: "CFBundleShortVersionString") ?? "(unknown app version)"
   }

   /// Returns the official 'build', defined in your project data.
   var build : String {
       return readFromInfoPlist(withKey: "CFBundleVersion") ?? "(unknown build number)"
   }

   /// Returns the minimum OS version defined in your project data.
   var minimumOSVersion : String {
    return readFromInfoPlist(withKey: "MinimumOSVersion") ?? "(unknown minimum OSVersion)"
   }

   /// Returns the copyright notice eventually defined in your project data.
   var copyrightNotice : String {
       return readFromInfoPlist(withKey: "NSHumanReadableCopyright") ?? "(unknown copyright notice)"
   }

   /// Returns the official bundle identifier defined in your project data.
   var bundleIdentifier : String {
       return readFromInfoPlist(withKey: "CFBundleIdentifier") ?? "(unknown bundle identifier)"
   }

   var developer : String { return "my awesome name" }

   // MARK: - Private stuff

   // lets hold a reference to the Info.plist of the app as Dictionary
   private let infoPlistDictionary = Bundle.main.infoDictionary

   /// Retrieves and returns associated values (of Type String) from info.Plist of the app.
   private func readFromInfoPlist(withKey key: String) -> String? {
    return infoPlistDictionary?[key] as? String
   }
}

使用:

print("Name of the app: \(AppInfo().appName)")

在Swift中,如果一个值不可用,就会使用nil。我认为你应该返回nil而不是自定义占位符字符串。 - Luca Angeletti
1
这就是为什么它是一个包装器:始终返回某些内容。nil情况并没有真正被“销毁”,它仍然存在,但已经预先处理。否则,您将不得不在应用程序的另一个地方处理“nil”情况。 - LukeSideWalker
1
谢谢伙计。另外,你的最后一个花括号在代码块之外。 :) - Mark Perkins
2
应用程序名称也可以是 CFBundleDisplayName - gondo

18

请使用Xcode 6的最终版本进行发布。

NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String

这里的 infoDictionary 后面的 "?" 字符很重要。


3
该系统的 "optional?, unwrap!" 确实很棒,清晰易读!我真的很喜欢它。 - Jeroen Bouma
@JeroenBouma 而且那个硬编码的字符串也很好。 - meaning-matters

16

这里有一种简单的方法来获取构建版本信息。

对于 Swift 4.X

 if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
     print(version)
   }

 if let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
     print(build)
   }

对于 Objective C

NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];

NSString * currentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];

如果出现任何问题,请告诉我。这个对我有效。


14

获取 AppNameAppVersionBuildNumber 的简单方式...

if let dict = NSBundle.mainBundle().infoDictionary {
   if let version = dict["CFBundleShortVersionString"] as? String,
       let bundleVersion = dict["CFBundleVersion"] as? String,
       let appName = dict["CFBundleName"] as? String {
           return "You're using \(appName) v\(version) (Build \(bundleVersion))."
   }
}

你为什么需要取消值的包装?据我所知,这些值中的任何一个都不可能为空。 - Michael
@Michael 有些人总是拆开可选值。有些人说你是对的。 - Dan Rosenstark
3
对我来说,Bundle.maininfoDictionary 是空的;可能是因为我是在一个框架内进行操作,而不是在可执行文件或应用程序中?Bundle(for: MyClass.self) 包含了预期的值。 - Raphael

8
在Swift中,我会将其作为UIApplication的扩展实现,就像这样:
extension UIApplication {

    func applicationVersion() -> String {

        return NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
    }

    func applicationBuild() -> String {

        return NSBundle.mainBundle().objectForInfoDictionaryKey(kCFBundleVersionKey as String) as! String
    }

    func versionBuild() -> String {

        let version = self.applicationVersion()
        let build = self.applicationBuild()

        return "v\(version)(\(build))"
    }
}

那么您只需要使用以下内容即可获得所需的一切:
let version = UIApplication.sharedApplication.applicationVersion() // 1
let build = UIApplication.sharedApplication.applicationBuild() // 80
let both = UIApplication.sharedApplication.versionBuild() // 1(80)

7

//返回应用程序的版本号

public static var appVersion: String? {
    return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
}

//返回应用程序的构建版本号

public static var appBuild: String? {
    return Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
}

2
另一种选择是在AppDelegate中定义变量:
var applicationVersion:String {
    return NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
}
var applicationBuild:String  {
    return NSBundle.mainBundle().objectForInfoDictionaryKey(kCFBundleVersionKey as String) as! String
}
var versionBuild:String  {
    let version = self.applicationVersion
    let build = self.applicationBuild
    return "version:\(version) build:(\(build))"
}

可以在AppDelegate中作为变量引用的内容

2

这段代码适用于Swift 3和Xcode 8:

let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接