Mam aplikację IOS z zapleczem platformy Azure i chciałbym rejestrować pewne zdarzenia, takie jak dane logowania i które wersje użytkowników aplikacji są uruchomione.
Jak mogę zwrócić wersję i numer kompilacji za pomocą Swift?
Mam aplikację IOS z zapleczem platformy Azure i chciałbym rejestrować pewne zdarzenia, takie jak dane logowania i które wersje użytkowników aplikacji są uruchomione.
Jak mogę zwrócić wersję i numer kompilacji za pomocą Swift?
Odpowiedzi:
EDYTOWAĆ
Zaktualizowano dla Swift 4.2
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
EDYTOWAĆ
Jak zauważył @azdev w nowej wersji Xcode, otrzymasz błąd kompilacji podczas wypróbowania mojego poprzedniego rozwiązania. Aby rozwiązać ten problem, po prostu edytuj go zgodnie z sugestią, aby rozpakować słownik pakietów za pomocą!
let nsObject: AnyObject? = Bundle.main.infoDictionary!["CFBundleShortVersionString"]
Zakończ edycję
Po prostu użyj tej samej logiki, co w Objective-C, ale z pewnymi drobnymi zmianami
//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
Mam nadzieję, że to ci pomoże.
David
infoDictionary
należy rozpakować za pomocą !
. Właśnie tego używam, umieszczonego w pliku Globals.swift:let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as String
let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Wiem, że już na nie odpowiedziano, ale osobiście uważam, że jest to trochę czystsze:
Swift 3.0:
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
Szybki <2.3
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
W ten sposób wersja if let zajmuje się przetwarzaniem warunkowym (ustawienie tekstu etykiety w moim przypadku), a jeśli infoDictionary lub CFBundleShortVersionString są zerowe, opcjonalne rozpakowanie spowoduje pominięcie kodu.
self.labelVersion.text
jest typem opcjonalnym, więc możesz przypisać bezpośrednioNSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String
let
, tylko zastanawiam się, dlaczego może być potrzebny. Dzięki!
Zaktualizowano dla Swift 3.0
W NS
-prefixes są teraz poszedł w Swift 3.0 i kilka właściwości / metody zostały zmienione nazwy być bardziej Swifty. Oto jak to teraz wygląda:
extension Bundle {
var releaseVersionNumber: String? {
return infoDictionary?["CFBundleShortVersionString"] as? String
}
var buildVersionNumber: String? {
return infoDictionary?["CFBundleVersion"] as? String
}
}
Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber
Stara zaktualizowana odpowiedź
Od czasu mojej pierwotnej odpowiedzi dużo pracuję z Frameworkami, dlatego chciałem zaktualizować swoje rozwiązanie do czegoś, co jest zarówno prostsze, jak i znacznie bardziej przydatne w środowisku obejmującym wiele pakietów:
extension NSBundle { var releaseVersionNumber: String? { return self.infoDictionary?["CFBundleShortVersionString"] as? String } var buildVersionNumber: String? { return self.infoDictionary?["CFBundleVersion"] as? String } }
Teraz to rozszerzenie będzie przydatne w aplikacjach do identyfikacji zarówno głównego pakietu, jak i wszelkich innych zawartych pakietów (takich jak wspólny framework do programowania rozszerzeń lub trzecie frameworki, takie jak AFNetworking):
NSBundle.mainBundle().releaseVersionNumber NSBundle.mainBundle().buildVersionNumber // or... NSBundle(URL: someURL)?.releaseVersionNumber NSBundle(URL: someURL)?.buildVersionNumber
Oryginalna odpowiedź
Chciałem poprawić niektóre z już opublikowanych odpowiedzi. Napisałem rozszerzenie klasy, które można dodać do łańcucha narzędzi, aby obsłużyć to w bardziej logiczny sposób.
extension NSBundle { class var applicationVersionNumber: String { if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]
tak jak? Ciąg {return version} return „Numer wersji niedostępny”}
class var applicationBuildNumber: String { if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String { return build } return "Build Number Not Available" } }
Teraz możesz uzyskać do niego łatwy dostęp poprzez:
let versionNumber = NSBundle.applicationVersionNumber
Wiem też, że już na nie odpowiedziano, ale podsumowałem poprzednie odpowiedzi:
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")"
}
}
Stosowanie:
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
}
W przypadku starszych wersji :
class func getVersion() -> String {
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
return version
}
return "no version info"
}
Więc jeśli chcesz ustawić tekst etykiety lub chcesz użyć gdzie indziej;
self.labelVersion.text = getVersion()
Dla Swift 4.0
let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!
Zrobiłem rozszerzenie w pakiecie
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
}
}
a następnie użyj go
versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"
W przypadku Swift 3.0 NSBundle nie działa, następujący kod działa idealnie.
let versionNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
as! String
a dla samego numeru kompilacji jest to:
let buildNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
as! String
Myląco „CFBundleVersion” to numer kompilacji wprowadzony w Xcode na Ogólne-> Tożsamość.
Xcode 9.4.1 Swift 4.1
Zwróć uwagę na użycie localizedInfoDictionary do wybrania odpowiedniej wersji językowej wyświetlanej nazwy pakietu.
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, przydatne rozszerzenie pakietu
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))"
}
}
Pakiet + Rozszerzenia.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
}
}
Stosowanie:
someLabel.text = Bundle.main.versionNumber
OP poprosił o numer wersji i numer kompilacji. Niestety większość odpowiedzi nie zapewnia obu tych opcji. Ponadto inni dodają niepotrzebne metody rozszerzenia. Oto jeden, który jest dość prosty i rozwiązuje problem 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 ""
}
}
Moja odpowiedź (z sierpnia 2015 r.), Biorąc pod uwagę Swift, ewoluuje:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Stworzyłem rozszerzenie dla 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"
}
}
Po przejrzeniu dokumentacji uważam, że następujące elementy są czystsze:
let version =
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString")
as? String
Źródło : „Zastosowanie tej metody jest lepsze niż innych metod dostępu, ponieważ zwraca zlokalizowaną wartość klucza, gdy jest on dostępny.”
W przypadku Swift 1.2 jest to:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Swift 3:
Numer wersji
if let versionNumberString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { // do something }
Numer kompilacji
if let buildNumberString = Bundle.main.infoDictionary?["CFBundleVersion"] as? String { // do something }
Szybki 4
func getAppVersion() -> String {
return "\(Bundle.main.infoDictionary!["CFBundleShortVersionString"] ?? "")"
}
Bundle.main.infoDictionary! ["CFBundleShortVersionString"]
Szybka stara składnia
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
}
}
Uwaga: Powinieneś użyć tej opcji, jeśli tutaj, jeśli wersja aplikacji lub kompilacja nie jest ustawiona, co spowoduje awarię, jeśli spróbujesz użyć! rozpakować.
Oto zaktualizowana wersja 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
// Najpierw pobierz nsObject, definiując jako opcjonalny AnyObject
let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject
// Następnie po prostu rzuć obiekt jako Ciąg, ale bądź ostrożny, możesz chcieć dwukrotnie sprawdzić zero
let version = nsObject as! String
Prosta funkcja narzędzia do zwracania wersji aplikacji jako 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
}
dla wszystkich zainteresowanych dostępna jest ładna i schludna biblioteka o nazwie SwifterSwift
dostępna na github, a także w pełni udokumentowana dla każdej wersji swift (patrz swifterswift.com ).
przy użyciu tej biblioteki odczytanie wersji aplikacji i numeru kompilacji byłoby tak proste, jak to:
import SwifterSwift
let buildNumber = SwifterSwift.appBuild
let version = SwifterSwift.appVersion
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
lblVersion.text = "Version \(version)"
}
Oto funkcja, której używam, aby zdecydować, czy wyświetlić stronę „Aktualizacja aplikacji”, czy nie. Zwraca numer kompilacji, którą konwertuję na 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")
}
Jeśli nigdy wcześniej nie zostanie użyty, zwróci 0, czyli mniej niż bieżący numer kompilacji. Aby nie wyświetlać takiego ekranu nowym użytkownikom, wystarczy dodać numer kompilacji po pierwszym logowaniu lub po zakończeniu wbudowania.
Swift 5 jako rozszerzenie UIApplication
extension UIApplication {
static var release: String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String? ?? "x.x"
}
static var build: String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String? ?? "x"
}
static var version: String {
return "\(release).\(build)"
}
}
przykład użycia:
print("release: \(UIApplication.release)")
print("build: \(UIApplication.build)")
print("version: \(UIApplication.version)")