Eu tenho um aplicativo IOS com um back-end do Azure e gostaria de registrar certos eventos, como logons e quais versões dos usuários do aplicativo estão em execução.
Como posso devolver a versão e criar o número usando o Swift?
Eu tenho um aplicativo IOS com um back-end do Azure e gostaria de registrar certos eventos, como logons e quais versões dos usuários do aplicativo estão em execução.
Como posso devolver a versão e criar o número usando o Swift?
Respostas:
EDITAR
Atualizado para o Swift 4.2
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
EDITAR
Como apontado por @azdev na nova versão do Xcode, você receberá um erro de compilação por tentar minha solução anterior. Para resolver isso, edite-o conforme sugerido para desembrulhar o dicionário de pacotes usando a!
let nsObject: AnyObject? = Bundle.main.infoDictionary!["CFBundleShortVersionString"]
Finalizar edição
Basta usar a mesma lógica que no Objective-C, mas com algumas pequenas alterações
//First get the nsObject by defining as an optional anyObject
let nsObject: AnyObject? = NSBundle.mainBundle().infoDictionary["CFBundleShortVersionString"]
//Then just cast the object as a String, but be careful, you may want to double check for nil
let version = nsObject as! String
Espero que isso ajude você.
David
infoDictionary
deve ser desembrulhado usando !
. Isto é o que eu estou usando, colocado em um arquivo Globals.swift:let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as String
let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Eu sei que isso já foi respondido, mas pessoalmente acho que isso é um pouco mais limpo:
Swift 3.0:
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
Swift <2.3
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
Dessa forma, a versão if let cuida do processamento condicional (configurando o texto do rótulo no meu caso) e se infoDictionary ou CFBundleShortVersionString forem nulos, o desempacotamento opcional fará com que o código seja ignorado.
self.labelVersion.text
é do tipo opcional, para que você possa atribuir diretamenteNSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String
let
, apenas se perguntando por que pode ser necessário. Obrigado!
Atualizado para o Swift 3.0
Os NS
prefixos-agora desapareceram no Swift 3.0 e várias propriedades / métodos mudaram de nome para serem mais Swifty. Aqui está o que isso parece agora:
extension Bundle {
var releaseVersionNumber: String? {
return infoDictionary?["CFBundleShortVersionString"] as? String
}
var buildVersionNumber: String? {
return infoDictionary?["CFBundleVersion"] as? String
}
}
Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber
Resposta atualizada antiga
Eu tenho trabalhado muito com Frameworks desde a minha resposta original, então eu queria atualizar minha solução para algo que seja mais simples e muito mais útil em um ambiente com vários pacotes:
extension NSBundle { var releaseVersionNumber: String? { return self.infoDictionary?["CFBundleShortVersionString"] as? String } var buildVersionNumber: String? { return self.infoDictionary?["CFBundleVersion"] as? String } }
Agora, esta extensão será útil em aplicativos para identificar o pacote principal e quaisquer outros pacotes incluídos (como uma estrutura compartilhada para programação de extensões ou terceira estrutura como AFNetworking), da seguinte forma:
NSBundle.mainBundle().releaseVersionNumber NSBundle.mainBundle().buildVersionNumber // or... NSBundle(URL: someURL)?.releaseVersionNumber NSBundle(URL: someURL)?.buildVersionNumber
Resposta original
Eu queria melhorar algumas das respostas já postadas. Eu escrevi uma extensão de classe que pode ser adicionada à sua cadeia de ferramentas para lidar com isso de uma maneira mais lógica.
extension NSBundle { class var applicationVersionNumber: String { if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]
Como? String {return version} return "Número da versão não disponível"}
class var applicationBuildNumber: String { if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String { return build } return "Build Number Not Available" } }
Então agora você pode acessar isso facilmente por:
let versionNumber = NSBundle.applicationVersionNumber
Sei também que isso já foi respondido, mas encerrei as respostas anteriores:
extension Bundle {
var releaseVersionNumber: String? {
return infoDictionary?["CFBundleShortVersionString"] as? String
}
var buildVersionNumber: String? {
return infoDictionary?["CFBundleVersion"] as? String
}
var releaseVersionNumberPretty: String {
return "v\(releaseVersionNumber ?? "1.0.0")"
}
}
Uso:
someLabel.text = Bundle.main.releaseVersionNumberPretty
Swift 3.1 :
class func getVersion() -> String {
guard let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
return "no version info"
}
return version
}
Para versões mais antigas :
class func getVersion() -> String {
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
return version
}
return "no version info"
}
Portanto, se você deseja definir o texto do rótulo ou usar em outro lugar;
self.labelVersion.text = getVersion()
Para Swift 4.0
let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!
Eu fiz uma extensão no pacote
extension Bundle {
var appName: String {
return infoDictionary?["CFBundleName"] as! String
}
var bundleId: String {
return bundleIdentifier!
}
var versionNumber: String {
return infoDictionary?["CFBundleShortVersionString"] as! String
}
var buildNumber: String {
return infoDictionary?["CFBundleVersion"] as! String
}
}
e depois use
versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"
Para o Swift 3.0, o NSBundle não funciona, o código a seguir funciona perfeitamente.
let versionNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
as! String
e apenas para o número da compilação, é:
let buildNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
as! String
Confusamente 'CFBundleVersion' é o número da compilação, conforme digitado no Xcode em Geral-> Identidade.
Xcode 9.4.1 Swift 4.1
Observe o uso do localizedInfoDictionary para selecionar a versão do idioma correto do nome de exibição do pacote configurável.
var displayName: String?
var version: String?
var build: String?
override func viewDidLoad() {
super.viewDidLoad()
// Get display name, version and build
if let displayName = Bundle.main.localizedInfoDictionary?["CFBundleDisplayName"] as? String {
self.displayName = displayName
}
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.version = version
}
if let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
self.build = build
}
}
Swift 4, Extensão útil para Bundle
import Foundation
public extension Bundle {
public var shortVersion: String {
if let result = infoDictionary?["CFBundleShortVersionString"] as? String {
return result
} else {
assert(false)
return ""
}
}
public var buildVersion: String {
if let result = infoDictionary?["CFBundleVersion"] as? String {
return result
} else {
assert(false)
return ""
}
}
public var fullVersion: String {
return "\(shortVersion)(\(buildVersion))"
}
}
Bundle + Extensions.swift
import Foundation
extension Bundle {
var versionNumber: String? {
return infoDictionary?["CFBundleShortVersionString"] as? String
}
var buildNumber: String? {
return infoDictionary?["CFBundleVersion"] as? String
}
var bundleName: String? {
return infoDictionary?["CFBundleName"] as? String
}
}
Uso:
someLabel.text = Bundle.main.versionNumber
O OP solicitou o número da versão e o número da compilação. Infelizmente, a maioria das respostas não fornece essas duas opções. Além disso, outros adicionam métodos de extensão desnecessários. Aqui está um que é bem simples e resolve o problema do OP:
// Example output: "1.0 (234)"
private func versionAndBuildNumber() -> String {
let versionNumber = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
if let versionNumber = versionNumber, let buildNumber = buildNumber {
return "\(versionNumber) (\(buildNumber))"
} else if let versionNumber = versionNumber {
return versionNumber
} else if let buildNumber = buildNumber {
return buildNumber
} else {
return ""
}
}
Minha resposta (em agosto de 2015), dado o Swift continuar evoluindo:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Eu criei uma extensão para UIApplication.
extension UIApplication {
static var appVersion: String {
let versionNumber = Bundle.main.infoDictionary?[IdentifierConstants.InfoPlist.versionNumber] as? String
let buildNumber = Bundle.main.infoDictionary?[IdentifierConstants.InfoPlist.buildNumber] as? String
let formattedBuildNumber = buildNumber.map {
return "(\($0))"
}
return [versionNumber,formattedBuildNumber].compactMap { $0 }.joined(separator: " ")
}
}
struct IdentifierConstants {
struct InfoPlist {
static let versionNumber = "CFBundleShortVersionString"
static let buildNumber = "CFBundleVersion"
}
}
Tendo examinado a documentação, acredito que o seguinte é mais limpo:
let version =
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString")
as? String
Fonte : "O uso desse método é preferível a outros métodos de acesso, pois retorna o valor localizado de uma chave quando uma está disponível."
Para o Swift 1.2, é:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Swift 3:
Número da versão
if let versionNumberString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { // do something }
Número da compilação
if let buildNumberString = Bundle.main.infoDictionary?["CFBundleVersion"] as? String { // do something }
Swift 4
func getAppVersion() -> String {
return "\(Bundle.main.infoDictionary!["CFBundleShortVersionString"] ?? "")"
}
Bundle.main.infoDictionary! ["CFBundleShortVersionString"]
Sintaxe antiga rápida
let appVer: AnyObject? = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"]
extension UIApplication {
static var appVersion: String {
if let appVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") {
return "\(appVersion)"
} else {
return ""
}
}
static var build: String {
if let buildVersion = NSBundle.mainBundle().objectForInfoDictionaryKey(kCFBundleVersionKey as String) {
return "\(buildVersion)"
} else {
return ""
}
}
static var versionBuild: String {
let version = UIApplication.appVersion
let build = UIApplication.build
var versionAndBuild = "v\(version)"
if version != build {
versionAndBuild = "v\(version)(\(build))"
}
return versionAndBuild
}
}
Atenção: Você deve usar if let here, caso a versão ou compilação do aplicativo não esteja definida, o que levará ao travamento se você tentar usar! desembrulhar.
Aqui está uma versão atualizada do Swift 3.2:
extension UIApplication
{
static var appVersion:String
{
if let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
{
return "\(appVersion)"
}
return ""
}
static var buildNumber:String
{
if let buildNum = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String)
{
return "\(buildNum)"
}
return ""
}
static var versionString:String
{
return "\(appVersion).\(buildNumber)"
}
}
public var appVersionNumberString: String {
get {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
}
}
SWIFT 4
// Primeiro obtenha o nsObject definindo como um AnyObject opcional
let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject
// Em seguida, basta converter o objeto como uma String, mas tenha cuidado, verifique duas vezes se não há
let version = nsObject as! String
para qualquer pessoa interessada, há uma biblioteca agradável e organizada chamada SwifterSwift
disponível no github e também totalmente documentada para todas as versões do swift (consulte swifterswift.com ).
usando esta biblioteca, ler a versão do aplicativo e o número da compilação seria tão fácil quanto isto:
import SwifterSwift
let buildNumber = SwifterSwift.appBuild
let version = SwifterSwift.appVersion
aqui está uma função que estou usando para decidir se mostra ou não uma página "o aplicativo atualizado". Ele retorna o número da compilação, que eu estou convertendo para um Int:
if let version: String = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
guard let intVersion = Int(version) else { return }
if UserDefaults.standard.integer(forKey: "lastVersion") < intVersion {
print("need to show popup")
} else {
print("Don't need to show popup")
}
UserDefaults.standard.set(intVersion, forKey: "lastVersion")
}
Se nunca usado antes, retornará 0, que é menor que o número da compilação atual. Para não mostrar essa tela para novos usuários, basta adicionar o número da compilação após o primeiro login ou quando a integração for concluída.
Função utilitário simples para retornar a versão do aplicativo como Int
func getAppVersion() -> Int {
if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
let appVersionClean = appVersion.replacingOccurrences(of: ".", with: "", options: NSString.CompareOptions.literal, range:nil)
if let appVersionNum = Int(appVersionClean) {
return appVersionNum
}
}
return 0
}
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.lblAppVersionValue.text = version
}
Pacote + Extension.swift (SwiftUI, Swift 5, Xcode 11)
Combinei idéias com algumas respostas e estendi um pouco:
Fundação de importação
pacote de extensão {
public var appVersionShort: String? {
if let result = infoDictionary?["CFBundleShortVersionString"] as? String {
return result
} else {
return "⚠️"
}
}
public var appVersionLong: String? {
if let result = infoDictionary?["CFBundleVersion"] as? String {
return result
} else {
return "⚠️"
}
}
public var appName: String? {
if let result = infoDictionary?["CFBundleName"] as? String {
return result
} else {
return "⚠️"
}
}
}
Exemplo de uso do SwiftUI
VStack {
Text("Version: \(Bundle.main.appVersionShort!) (\(Bundle.main.appVersionLong!))")
.font(.subheadline)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
lblVersion.text = "Version \(version)"
}