Obtendo informações de versão e construção com Swift

91

Estou tentando obter acesso ao NSBundle principal para recuperar informações de versão e compilação. O fato é que eu quero tentar rapidamente, eu sei como recuperá-lo em Objective-C com Build.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];. Ainda não sei por onde começar com swift, tentei escrevê-lo na nova sintaxe sem sucesso.

Ken-UbiDex
fonte
2
Mostre as tentativas que você já fez. É muito semelhante à implementação Objective-C.
Mick MacCallum
Swift 2.3 de janeiro de 2017: deixe sVer = NSBundle.mainBundle (). InfoDictionary? ["CFBundleShortVersionString"] como? String permite que sBuild = NSBundle.mainBundle (). InfoDictionary? ["CFBundleVersion"] como? String self.myVersionLabel.text = String (formato: "Versão% @ Build% @", sVer !, sBuild!)
Matthew Ferguson

Respostas:

167

O que havia de errado com a sintaxe do Swift? Isso parece funcionar:

if let text = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
    print(text)
}
Connor
fonte
2
Por que isso foi rejeitado? Eu acho que pode ser mais natural como um, letmas de outra forma parece correto.
Tommy
Ah, esqueci o "as String" para que a variável o aceitasse como string. Obrigado.
Ken-UbiDex
2
Isso parece estar quebrado com o XCode 6 beta 3
Frédéric Adda
2
Isso funcionou para mim no Xcode 6 beta 5:let text = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]! as String
E. Barnes
@Dean Parece que eles alteraram infoDictionary para retornar um opcional. Eu editei a resposta
Connor
118

Versão 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)"
} 

Versão 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 visto aqui .

Dan Rosenstark
fonte
1
Você obtém a mesma chave duas vezes, deve usar "CFBundleVersion" para a versão. Eu acho que é uma cópia / erro de digitação anterior :)
foOg
Obrigado @foOg foi um erro de digitação. Na verdade, é ao contrário: o curto é a versão, o normal é a construção. Estranho, eu sei.
Dan Rosenstark
Versão 3 do Swift. se deixar infoPath = Bundle.main.path (forResource: "Info.plist", ofType: nulo), deixe infoAttr = tentar? FileManager.default.attributesOfItem (atPath: infoPath), deixe infoDate = infoAttr [.creationDate] como? Data {return infoDate} data de retorno ()
Ryan X
18

Para a versão final do Xcode 6, use

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

O "?" caractere após infoDictionary é importante aqui

JulianM
fonte
1
Droga. Eu adoro todo esse "opcional? Desembrulhe!" sistema, é cristalino e muito fácil de ler!
Jeroen Bouma,
14

Aqui está uma maneira simples de obter o Build e a versão.

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 Objetivo C

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

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

Deixe-me saber se houver algum problema. Isso está funcionando para mim.

Ashu
fonte
13

Caminho rápido para AppName, AppVersione 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
fonte
Por que você precisa desembrulhar os valores? Que eu saiba, é impossível que qualquer um desses valores seja nulo
Michael
@Michael algumas pessoas SEMPRE desembrulham valores opcionais. Algumas pessoas dizem que você está certo.
Dan Rosenstark
2
Bundle.maintinha um vazio infoDictionarypara mim; talvez porque estou fazendo isso de dentro de uma estrutura, não de um executável ou aplicativo? Bundle(for: MyClass.self)contém os valores esperados.
Raphael de
7

Em resumo, eu faria isso como uma extensão para UIApplication, assim:

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

Em seguida, você pode usar o seguinte para obter tudo o que precisa:

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

// Retorna o número da versão do aplicativo

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

// Retorna o número da compilação do aplicativo

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

Swift 5.0

Eu criei um wrapper para Swift 5 para obter algumas strings relacionadas ao aplicativo em um lugar em todos os meus aplicativos, chamado 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
     }
}

Você pode usá-lo assim:

print("The apps name = \(AppInfo.appname)")
LukeSideWalker
fonte
Quando em Swift, um valor não está disponível, nil é usado. IMO você deve retornar nil em vez de strings de placeholder personalizadas.
Luca Angeletti
É por isso que é um invólucro: para sempre receber algo em troca A situação nula não está realmente "destruída", ela ainda está lá, mas já pré-tratada. Caso contrário, você teria que lidar com a situação "nulo" em outro lugar em seu aplicativo.
LukeSideWalker
obrigado amigo. além disso, a última chave está fora do bloco de código. :)
Mark Perkins
2
o nome do aplicativo também pode 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
fonte
2

Para Swift 3, Substitua NSBundle por Bundle e mainBundle é substituído simplesmente por main.

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

[Atualização: Xcode 6.3.1] Tentei todos os itens acima e nenhum deles funciona no Xcode 6.3.1, mas descobri que:

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

Outra opção é definir no AppDelegate as variáveis:

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 podem ser referenciados como variáveis ​​no AppDelegate

user3620768
fonte
0

Swift 3:

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

Versão 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
fonte
0

Para ter resultado para a estrutura, você pode usar

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

ou em testes

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