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.

Ken-UbiDex
la source
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)
}
Connor
la source
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 .

Dan Rosenstark
la source
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

JulianM
la source
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.

Ashu
la source
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))."
   }
}
Chris
la source
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)
Jiri Trecak
la source
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
}
Pratyush Pratik
la source
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)")
LukeSideWalker
la source
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"
Crashalot
la source
2

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

let AppVersion = Bundle.main.infoDictionary!["CFBundleVersion"] as! String
Tarika Chawla
la source
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)!
SunburstEnzo
la source
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

user3620768
la source
0

Swift 3:

let textVersion
 = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
Zvonimir Taslak
la source
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()
Ryan X
la source
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
yoAlex5
la source