Obtener información de versión y compilación con Swift

92

Estoy intentando obtener acceso al NSBundle principal para recuperar la información de versión y compilación. La cosa es que quiero probarlo rápidamente, sé cómo recuperarlo en Objective-C con Build.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];. Sin embargo, no sé por dónde empezar con swift, he intentado escribirlo en la nueva sintaxis sin éxito.

Ken-UbiDex
fuente
2
Muestra los intentos que ya has hecho. Es muy similar a la implementación de Objective-C.
Mick MacCallum
Enero de 2017 swift 2.3: deje sVer = NSBundle.mainBundle (). InfoDictionary? ["CFBundleShortVersionString"] como? String let sBuild = NSBundle.mainBundle (). InfoDictionary? ["CFBundleVersion"] como? String self.myVersionLabel.text = String (formato: "Versión% @ Build% @", sVer !, sBuild!)
Matthew Ferguson

Respuestas:

167

¿Qué pasaba con la sintaxis de Swift? Esto parece funcionar:

if let text = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
    print(text)
}
Connor
fuente
2
¿Por qué se votó en contra? Supongo que podría ser más natural, letpero por lo demás parece correcto.
Tommy
Ah, olvidé el "como cadena" para que la variable lo aceptara como una cadena. Gracias.
Ken-UbiDex
2
Eso parece estar roto con XCode 6 beta 3
Frédéric Adda
2
Esto funcionó para mí en Xcode 6 beta 5:let text = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]! as String
E. Barnes
@Dean Parece que cambiaron infoDictionary para devolver un opcional. He editado la respuesta
Connor
118

Versión 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)"
} 

Versión 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)"
}

como se ve aquí .

Dan Rosenstark
fuente
1
Obtiene la misma clave dos veces, debe usar "CFBundleVersion" para la versión. Supongo que es una copia / error tipográfico anterior :)
foOg
Gracias @foOg fue un error tipográfico. De hecho, es al revés: la corta es la versión, la normal es la compilación. Extraño, lo sé.
Dan Rosenstark
Versión Swift 3. if let infoPath = Bundle.main.path (forResource: "Info.plist", ofType: nil), let infoAttr = try? FileManager.default.attributesOfItem (atPath: infoPath), deje infoDate = infoAttr [.creationDate] como? Fecha {return infoDate} Fecha de regreso ()
Ryan X
18

Para la versión final de Xcode 6 use

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

Los "?" carácter después del infoDiccionario es importante aquí

JulianM
fuente
1
Maldición. Seguro que me encanta todo este "¿opcional? ¡Desenvolver!" sistema, es muy claro y muy fácil de leer.
Jeroen Bouma
14

Esta es una forma sencilla de obtener compilación y versión.

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

Para el objetivo C

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

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

Avísame si hay algún problema. Esto es trabajo para mí.

Ashu
fuente
13

Camino rápido para AppName, AppVersiony 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
fuente
¿Por qué necesitarías desenvolver los valores? Que yo sepa, es imposible que ninguno de esos valores sea nulo
Michael
@Michael algunas personas SIEMPRE desenvuelven valores opcionales. Algunas personas dicen que tienes razón.
Dan Rosenstark
2
Bundle.maintenía un vacío infoDictionarypara mí; tal vez porque lo hago desde un marco, no un ejecutable o una aplicación? Bundle(for: MyClass.self)contiene los valores esperados.
Raphael
7

Rápidamente, lo convertiría en una extensión para UIApplication, así:

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

Entonces puede usar lo siguiente para obtener todo lo que necesita:

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

// Devuelve el número de versión de la aplicación

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

// Devuelve el número de compilación de la aplicación

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

Swift 5.0

Creé un contenedor para Swift 5 para obtener algunas cadenas relacionadas con la aplicación en un solo lugar en todas mis aplicaciones, llamado 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
     }
}

Puedes usarlo así:

print("The apps name = \(AppInfo.appname)")
LukeSideWalker
fuente
Cuando en Swift un valor no está disponible, se usa nil. En mi opinión, debe devolver nil en lugar de cadenas de marcador de posición personalizadas.
Luca Angeletti
Por eso es un envoltorio: para obtener siempre algo a cambio. La situación nula no está realmente "destruida", todavía está ahí, pero ya pre-manejada. De lo contrario, tendría que manejar la situación "nula" en otro lugar de su aplicación.
LukeSideWalker
gracias amigo. Además, la última llave está fuera del bloque de código. :)
Mark Perkins
2
El nombre de la aplicación también puede serCFBundleDisplayName
gondo
2

Este código funciona para Swift 3, Xcode 8:

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

Para Swift 3, reemplace NSBundle con Bundle y mainBundle se reemplaza simplemente por main.

let AppVersion = Bundle.main.infoDictionary!["CFBundleVersion"] as! String
Tarika Chawla
fuente
1

[Actualización: Xcode 6.3.1] Probé todo lo anterior y ninguno de estos funciona en Xcode 6.3.1 pero descubrí que esto sí:

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

Otra opción es definir en el AppDelegate las 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))"
}

que se pueden referenciar como variables en AppDelegate

user3620768
fuente
0

Swift 3:

let textVersion
 = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
Zvonimir Taslak
fuente
0

Versión 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
fuente
0

Para tener un resultado para el marco, puede usar

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

o en pruebas

let version = Bundle(for: <SomeClass>.self).infoDictionary?["CFBundleShortVersionString"] as? String
yoAlex5
fuente