Ich habe eine IOS-App mit einem Azure-Back-End und möchte bestimmte Ereignisse protokollieren, z. B. Anmeldungen und welche Versionen der App-Benutzer ausgeführt werden.
Wie kann ich die Version und die Build-Nummer mit Swift zurückgeben?
Ich habe eine IOS-App mit einem Azure-Back-End und möchte bestimmte Ereignisse protokollieren, z. B. Anmeldungen und welche Versionen der App-Benutzer ausgeführt werden.
Wie kann ich die Version und die Build-Nummer mit Swift zurückgeben?
Antworten:
BEARBEITEN
Aktualisiert für Swift 4.2
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
BEARBEITEN
Wie von @azdev in der neuen Version von Xcode hervorgehoben, wird beim Kompilieren meiner vorherigen Lösung ein Kompilierungsfehler angezeigt. Um dies zu lösen, bearbeiten Sie es einfach wie vorgeschlagen, um das Bundle-Wörterbuch mit einem!
let nsObject: AnyObject? = Bundle.main.infoDictionary!["CFBundleShortVersionString"]
Bearbeiten beenden
Verwenden Sie einfach dieselbe Logik wie in Objective-C, jedoch mit einigen kleinen Änderungen
//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
Ich hoffe das hilft dir weiter.
David
infoDictionary
sollte mit ausgepackt werden !
. Dies ist, was ich benutze, in eine Globals.swift-Datei gelegt:let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as String
let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Ich weiß, dass dies bereits beantwortet wurde, aber ich persönlich denke, dass dies ein wenig sauberer ist:
Swift 3.0:
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
Schnell <2.3
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
Auf diese Weise kümmert sich die if let-Version um die bedingte Verarbeitung (in meinem Fall das Festlegen des Beschriftungstextes), und wenn infoDictionary oder CFBundleShortVersionString gleich Null sind, wird der Code beim optionalen Entpacken übersprungen.
self.labelVersion.text
ist optionaler Typ, so dass Sie direkt zuweisen könnenNSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String
let
einig, dass es definitiv vorsichtiger ist und frage mich nur, warum es nötig sein könnte. Vielen Dank!
Aktualisiert für Swift 3.0
Die NS
Präfixe sind jetzt in Swift 3.0 verschwunden und einige Eigenschaften / Methoden haben den Namen geändert, um schneller zu sein. So sieht das jetzt aus:
extension Bundle {
var releaseVersionNumber: String? {
return infoDictionary?["CFBundleShortVersionString"] as? String
}
var buildVersionNumber: String? {
return infoDictionary?["CFBundleVersion"] as? String
}
}
Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber
Alte aktualisierte Antwort
Ich habe seit meiner ursprünglichen Antwort viel mit Frameworks gearbeitet, daher wollte ich meine Lösung auf etwas aktualisieren, das in einer Umgebung mit mehreren Bundles sowohl einfacher als auch viel nützlicher ist:
extension NSBundle { var releaseVersionNumber: String? { return self.infoDictionary?["CFBundleShortVersionString"] as? String } var buildVersionNumber: String? { return self.infoDictionary?["CFBundleVersion"] as? String } }
Jetzt ist diese Erweiterung in Apps nützlich, um sowohl das Hauptpaket als auch alle anderen enthaltenen Pakete (z. B. ein gemeinsames Framework für die Erweiterungsprogrammierung oder dritte Frameworks wie AFNetworking) zu identifizieren:
NSBundle.mainBundle().releaseVersionNumber NSBundle.mainBundle().buildVersionNumber // or... NSBundle(URL: someURL)?.releaseVersionNumber NSBundle(URL: someURL)?.buildVersionNumber
Ursprüngliche Antwort
Ich wollte einige der bereits veröffentlichten Antworten verbessern. Ich habe eine Klassenerweiterung geschrieben, die zu Ihrer Werkzeugkette hinzugefügt werden kann, um dies logischer zu handhaben.
extension NSBundle { class var applicationVersionNumber: String { if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]
wie? String {return version} return "Versionsnummer nicht verfügbar"}
class var applicationBuildNumber: String { if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String { return build } return "Build Number Not Available" } }
Jetzt können Sie einfach darauf zugreifen, indem Sie:
let versionNumber = NSBundle.applicationVersionNumber
Ich weiß auch, dass dies bereits beantwortet wurde, aber ich habe die vorherigen Antworten zusammengefasst:
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")"
}
}
Verwendungszweck:
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
}
Für ältere Versionen :
class func getVersion() -> String {
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
return version
}
return "no version info"
}
Wenn Sie also Beschriftungstext festlegen oder woanders verwenden möchten;
self.labelVersion.text = getVersion()
Für Swift 4.0
let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!
Ich habe eine Erweiterung für Bundle erstellt
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
}
}
und dann benutze es
versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"
Für Swift 3.0 funktioniert NSBundle nicht. Der folgende Code funktioniert einwandfrei.
let versionNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
as! String
und für nur die Build-Nummer ist es:
let buildNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
as! String
Verwirrenderweise ist 'CFBundleVersion' die Build- Nummer, wie sie in Xcode unter Allgemein-> Identität eingegeben wurde.
Xcode 9.4.1 Swift 4.1
Beachten Sie die Verwendung von localizedInfoDictionary, um die richtige Sprachversion des Anzeigenamens des Bundles zu ermitteln.
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, nützliche Erweiterung für 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
}
}
Verwendungszweck:
someLabel.text = Bundle.main.versionNumber
OP fragte sowohl nach der Versionsnummer als auch nach der Build-Nummer. Leider bieten die meisten Antworten nicht beide Optionen. Darüber hinaus fügen andere unnötige Erweiterungsmethoden hinzu. Hier ist eine, die ziemlich einfach ist und das Problem von OP löst:
// 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 ""
}
}
Meine Antwort (Stand August 2015) angesichts von Swift entwickelt sich weiter:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Ich habe eine Erweiterung für UIApplication erstellt.
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"
}
}
Nachdem ich mir die Dokumentation angesehen habe, glaube ich, dass Folgendes sauberer ist:
let version =
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString")
as? String
Quelle : "Die Verwendung dieser Methode wird anderen Zugriffsmethoden vorgezogen, da sie den lokalisierten Wert eines Schlüssels zurückgibt, wenn einer verfügbar ist."
Für Swift 1.2 ist es:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Swift 3:
Versionsnummer
if let versionNumberString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { // do something }
Build-Nummer
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"]
Schnelle alte Syntax
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
}
}
Achtung: Sie sollten verwenden, wenn Sie dies hier zulassen, falls die App-Version oder der Build nicht festgelegt ist. Dies führt zu einem Absturz, wenn Sie versuchen, diese zu verwenden! auspacken.
Hier ist eine aktualisierte Version für 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
// Holen Sie sich zuerst das nsObject, indem Sie es als optionales AnyObject definieren
let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject
// Dann wandle das Objekt einfach als String um, aber sei vorsichtig, vielleicht möchtest du noch einmal nach Null suchen
let version = nsObject as! String
Für alle Interessierten gibt es eine schöne und gepflegte Bibliothek mit dem Namen SwifterSwift
verfügbar unter Github und auch für jede Version von schnellen (siehe vollständig dokumentiert swifterswift.com ).
Mit dieser Bibliothek ist das Lesen der App-Version und der Build-Nummer so einfach:
import SwifterSwift
let buildNumber = SwifterSwift.appBuild
let version = SwifterSwift.appVersion
Hier ist eine Funktion, mit der ich entscheide, ob eine Seite "Die App aktualisiert" angezeigt werden soll oder nicht. Es gibt die Build-Nummer zurück, die ich in ein Int konvertiere:
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")
}
Wenn es noch nie zuvor verwendet wurde, wird 0 zurückgegeben, was niedriger als die aktuelle Build-Nummer ist. Um neuen Benutzern einen solchen Bildschirm nicht anzuzeigen, fügen Sie einfach die Build-Nummer nach der ersten Anmeldung oder nach Abschluss des Onboarding hinzu.
Einfache Dienstprogrammfunktion zum Zurückgeben der App-Version als 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
}
Bundle + Extension.swift (SwiftUI, Swift 5, Xcode 11)
Ich habe Ideen aus einigen Antworten kombiniert und ein wenig erweitert:
Foundation importieren
Erweiterungspaket {
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 "⚠️"
}
}
}}
SwiftUI Beispiel verwenden
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)"
}