Obtenir des informations sur la version et la construction avec Swift


92

J'essaie d'accéder au NSBundle principal pour récupérer les informations de version et de construction. Le truc, c'est que je veux l'essayer rapidement, je sais comment le récupérer en Objective-C avec Build.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];. Pourtant, je ne sais pas par où commencer avec swift, j'ai essayé de l'écrire dans la nouvelle syntaxe en vain.


2
Montrez les tentatives que vous avez déjà faites. C'est très similaire à l'implémentation d'Objective-C.
Mick MacCallum

Janvier 2017 swift 2.3: laissez sVer = NSBundle.mainBundle (). InfoDictionary? ["CFBundleShortVersionString"] as? String let sBuild = NSBundle.mainBundle (). InfoDictionary? ["CFBundleVersion"] as? String self.myVersionLabel.text = String (format: "Version% @ Build% @", sVer !, sBuild!)
Matthew Ferguson

Réponses:


167

Quel était le problème avec la syntaxe Swift? Cela semble fonctionner:

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

2
Pourquoi ce vote a-t-il été rejeté? Je suppose que cela pourrait être plus naturel, letmais cela semble correct.
Tommy

Ah, j'ai oublié le "as String" donc la variable l'accepterait comme une chaîne. Merci.
Ken-UbiDex

2
Cela semble être cassé avec XCode 6 beta 3
Frédéric Adda

2
Cela a fonctionné pour moi dans Xcode 6 beta 5:let text = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]! as String
E. Barnes

@Dean On dirait qu'ils ont changé infoDictionary pour renvoyer un optionnel. J'ai modifié la réponse
Connor

118

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

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

comme vu ici .


1
Vous obtenez la même clé deux fois, vous devez utiliser "CFBundleVersion" pour la version. Je suppose que c'est une copie / une faute de frappe :)
foOg

Merci @foOg c'était une faute de frappe. En fait, c'est à l'envers: la version courte est la version, la version normale est la construction. Bizarre, je sais.
Dan Rosenstark

Version Swift 3. si laissez infoPath = Bundle.main.path (forResource: "Info.plist", ofType: nil), laissez infoAttr = essayez? FileManager.default.attributesOfItem (atPath: infoPath), laissez infoDate = infoAttr [.creationDate] comme? Date {return infoDate} date de retour ()
Ryan X

18

Pour la version finale de Xcode 6, utilisez

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

Le "?" le caractère après infoDictionary est important ici


1
Zut. J'adore vraiment tout ce "facultatif ?, déballer!" système, il est limpide et si facile à lire!
Jeroen Bouma

14

Voici un moyen simple d'obtenir la version et la version.

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

Pour l'objectif C

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

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

Faites-moi savoir si un problème. Cela fonctionne pour moi.


13

Une manière rapide pour AppName, AppVersionet BuildNumber...

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

Pourquoi auriez-vous besoin de dévoiler les valeurs? À ma connaissance, il est impossible que l'une de ces valeurs soit nulle
Michael

@Michael certaines personnes déballent TOUJOURS les valeurs facultatives. Certaines personnes disent que vous avez raison.
Dan Rosenstark

2
Bundle.mainavait un vide infoDictionarypour moi; peut-être parce que je le fais à partir d'un cadre, pas d'un exécutable ou d'une application? Bundle(for: MyClass.self)contient les valeurs attendues.
Raphael

7

En swift, je le ferais comme extension pour UIApplication, comme ceci:

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

Ensuite, vous pouvez simplement utiliser ce qui suit pour obtenir tout ce dont vous avez besoin:

let version = UIApplication.sharedApplication.applicationVersion() // 1
let build = UIApplication.sharedApplication.applicationBuild() // 80
let both = UIApplication.sharedApplication.versionBuild() // 1(80)

7

// Renvoie le numéro de version de l'application

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

// Renvoie le numéro de build de l'application

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

6

Swift 5.0

J'ai créé un wrapper pour Swift 5 pour obtenir des chaînes liées aux applications à un seul endroit de toutes mes applications, appelé AppInfo .

struct AppInfo {

var appName : String {
    return readFromInfoPlist(withKey: "CFBundleName") ?? "(unknown app name)"
}

var version : String {
    return readFromInfoPlist(withKey: "CFBundleShortVersionString") ?? "(unknown app version)"
}

var build : String {
    return readFromInfoPlist(withKey: "CFBundleVersion") ?? "(unknown build number)"
}

var minimumOSVersion : String {
    return readFromInfoPlist(withKey: "MinimumOSVersion") ?? "(unknown minimum OSVersion)"
}

var copyrightNotice : String {
    return readFromInfoPlist(withKey: "NSHumanReadableCopyright") ?? "(unknown copyright notice)"
}

var bundleIdentifier : String {
    return readFromInfoPlist(withKey: "CFBundleIdentifier") ?? "(unknown bundle identifier)"
}

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

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

Vous pouvez l'utiliser comme ceci:

print("The apps name = \(AppInfo.appname)")

Quand dans Swift, une valeur n'est pas disponible, nul est utilisé. IMO, vous devez renvoyer nil au lieu de chaînes d'espace réservé personnalisées.
Luca Angeletti le

C'est pourquoi c'est un emballage: pour toujours récupérer quelque chose. La situation nulle n'est pas vraiment "détruite", elle est toujours là, mais déjà pré-traitée. Sinon, vous devrez gérer la situation «nil» à un autre endroit de votre application.
LukeSideWalker

merci mon pote. aussi, votre dernière accolade est en dehors du bloc de code. :)
Mark Perkins

2
le nom de l'application peut être aussiCFBundleDisplayName
gondo

2

Ce code fonctionne pour Swift 3, Xcode 8:

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

2

Pour Swift 3, remplacez NSBundle par Bundle et mainBundle est simplement remplacé par main.

let AppVersion = Bundle.main.infoDictionary!["CFBundleVersion"] as! String

1

[Mise à jour: Xcode 6.3.1] J'ai essayé tout ce qui précède et aucun de ceux-ci ne fonctionne dans Xcode 6.3.1 mais j'ai trouvé que cela fonctionne:

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

1

Une autre option consiste à définir dans l'AppDelegate les variables:

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

qui peuvent être référencées en tant que variables dans AppDelegate


0

Swift 3:

let textVersion
 = Bundle.main.infoDictionary?["CFBundleVersion"] as? String

0

Version SWIFT 3

if 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()

0

Pour avoir un résultat pour le cadre, vous pouvez utiliser

let version = Bundle(for: type(of: self)).infoDictionary?["CFBundleShortVersionString"] as? String

ou en tests

let version = Bundle(for: <SomeClass>.self).infoDictionary?["CFBundleShortVersionString"] as? String
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.