Pobieranie informacji o wersji i kompilacji za pomocą Swift

92

Próbuję uzyskać dostęp do głównego pakietu NSBundle w celu pobrania informacji o wersji i kompilacji. Chodzi o to, że chcę to szybko wypróbować, wiem, jak go odzyskać w Objective-C za pomocą Build.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];. Jednak nie wiem, od czego zacząć ze swiftem, bezskutecznie próbowałem napisać go w nowej składni.

Ken-UbiDex
źródło
2
Pokaż podjęte już próby. Jest bardzo podobny do implementacji Objective-C.
Mick MacCallum
Styczeń 2017 swift 2.3: let sVer = NSBundle.mainBundle (). InfoDictionary? ["CFBundleShortVersionString"] as? Ciąg let sBuild = NSBundle.mainBundle (). InfoDictionary? ["CFBundleVersion"] as? String self.myVersionLabel.text = String (format: "Wersja% @ Build% @", sVer !, sBuild!)
Matthew Ferguson

Odpowiedzi:

167

Co było nie tak ze składnią Swift? To wydaje się działać:

if let text = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
    print(text)
}
Connor
źródło
2
Dlaczego ten głos został odrzucony? Myślę, że może to być bardziej naturalne, letale poza tym wygląda poprawnie.
Tommy,
Ach, zapomniałem „as String”, więc zmienna przyjęłaby ją jako ciąg. Dziękuję Ci.
Ken-UbiDex
2
To wydaje się być zepsute w XCode 6 beta 3
Frédéric Adda
2
To zadziałało dla mnie w Xcode 6 beta 5:let text = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]! as String
E. Barnes
@Dean Wygląda na to, że zmienili infoDictionary, aby zwracał opcjonalny. Zmieniłem odpowiedź
Connor
118

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

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

jak widać tutaj .

Dan Rosenstark
źródło
1
Dostajesz ten sam klucz dwukrotnie, użyj "CFBundleVersion" dla wersji.
Wydaje
Dzięki @foOg, to była literówka. W rzeczywistości jest odwrotnie: krótka to wersja, a zwykła to kompilacja. Wiem, dziwne.
Dan Rosenstark
Wersja Swift 3. jeśli niech infoPath = Bundle.main.path (forResource: "Info.plist", ofType: nil), niech infoAttr = try? FileManager.default.attributesOfItem (atPath: infoPath), niech infoDate = infoAttr [.creationDate] as? Data {return infoDate} return Date ()
Ryan X
18

Do ostatecznej wersji Xcode 6 użyj

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

„?” postać po infoDictionary jest tu ważna

JulianM
źródło
1
Cholera. Z pewnością uwielbiam to całe „opcjonalne ?, rozpakowywanie!” system, jest krystalicznie czysty i łatwy do odczytania!
Jeroen Bouma
14

Oto prosty sposób na uzyskanie kompilacji i wersji.

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

W przypadku celu C

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

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

Daj mi znać, jeśli jakiś problem. To działa dla mnie.

Ashu
źródło
13

Swifty sposób AppName, AppVersiona 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
źródło
Dlaczego miałbyś rozpakowywać wartości? O ile mi wiadomo, żadna z tych wartości nie może być zerowa
Michael
@Michael Niektórzy ludzie ZAWSZE rozpakowują wartości opcjonalne. Niektórzy mówią, że masz rację.
Dan Rosenstark
2
Bundle.mainmiał infoDictionarydla mnie pusty ; może dlatego, że robię to w ramach, a nie w pliku wykonywalnym lub aplikacji? Bundle(for: MyClass.self)zawiera oczekiwane wartości.
Raphael
7

Szybko zrobiłbym to jako rozszerzenie dla UIApplication, w ten sposób:

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

Następnie możesz po prostu użyć następujących, aby uzyskać wszystko, czego potrzebujesz:

let version = UIApplication.sharedApplication.applicationVersion() // 1
let build = UIApplication.sharedApplication.applicationBuild() // 80
let both = UIApplication.sharedApplication.versionBuild() // 1(80)
Jiri Trecak
źródło
7

// Zwraca numer wersji aplikacji

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

// Zwróć numer kompilacji aplikacji

public static var appBuild: String? {
    return Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
}
Pratyush Pratik
źródło
6

Swift 5.0

Utworzyłem opakowanie dla Swift 5, aby uzyskać niektóre ciągi znaków związanych z aplikacjami w jednym miejscu we wszystkich moich aplikacjach, o nazwie 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
     }
}

Możesz go używać w ten sposób:

print("The apps name = \(AppInfo.appname)")
LukeSideWalker
źródło
W języku Swift wartość nie jest dostępna, używane jest zero. IMO powinieneś zwrócić nil zamiast niestandardowych ciągów znaków zastępczych.
Luca Angeletti
Dlatego jest to opakowanie: zawsze coś odzyskać. Sytuacja zerowa nie jest tak naprawdę „zniszczona”, nadal istnieje, ale jest już wstępnie załatwiona. W przeciwnym razie musiałbyś zająć się sytuacją „zerową” w innym miejscu aplikacji.
LukeSideWalker
dzięki ziom. również ostatni nawias klamrowy znajduje się poza blokiem kodu. :)
Mark Perkins
2
nazwa aplikacji może być równieżCFBundleDisplayName
gondo
2

Ten kod działa dla Swift 3, Xcode 8:

let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"
Crashalot
źródło
2

W przypadku Swift 3 zamień NSBundle na Bundle, a mainBundle zostanie zastąpiony po prostu przez main.

let AppVersion = Bundle.main.infoDictionary!["CFBundleVersion"] as! String
Tarika Chawla
źródło
1

[Aktualizacja: Xcode 6.3.1] Wypróbowałem wszystkie powyższe i żadne z nich nie działa w Xcode 6.3.1, ale stwierdziłem, że to działa:

(NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String)!
SunburstEnzo
źródło
1

Inną opcją jest zdefiniowanie w AppDelegate zmiennych:

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

do których można się odwoływać jako zmienne w AppDelegate

user3620768
źródło
0

Swift 3:

let textVersion
 = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
Zvonimir Taslak
źródło
0

Wersja 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
źródło
0

Aby uzyskać wynik dla frameworka, którego możesz użyć

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

lub w testach

let version = Bundle(for: <SomeClass>.self).infoDictionary?["CFBundleShortVersionString"] as? String
yoAlex5
źródło