Version abrufen und Informationen mit Swift erstellen

89

Ich versuche, Zugriff auf das Haupt-NSBundle zu erhalten, um Versions- und Build-Informationen abzurufen. Die Sache ist, ich möchte es schnell versuchen, ich weiß, wie man es in Objective-C mit abruft Build.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];. Ich weiß jedoch nicht, wo ich mit Swift anfangen soll. Ich habe versucht, es ohne Erfolg in der neuen Syntax zu schreiben.

Ken-UbiDex
quelle
2
Zeigen Sie die Versuche an, die Sie bereits unternommen haben. Es ist der Objective-C-Implementierung sehr ähnlich.
Mick MacCallum
Jan 2017 swift 2.3: let sVer = NSBundle.mainBundle (). InfoDictionary? ["CFBundleShortVersionString"] as? String let sBuild = NSBundle.mainBundle (). InfoDictionary? ["CFBundleVersion"] as? String self.myVersionLabel.text = String (Format: "Version% @ Build% @", sVer!, SBuild!)
Matthew Ferguson

Antworten:

163

Was war falsch an der Swift-Syntax? Das scheint zu funktionieren:

if let text = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
    print(text)
}
Connor
quelle
2
Warum wurde das abgelehnt? Ich denke, es könnte natürlicher sein als, letaber es sieht ansonsten richtig aus.
Tommy
Ah, ich habe das "as String" vergessen, damit die Variable es als String akzeptiert. Danke dir.
Ken-UbiDex
2
Das scheint mit XCode 6 Beta 3
Frédéric Adda
2
Dies funktionierte für mich in Xcode 6 Beta 5:let text = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]! as String
E. Barnes
@ Dean Es sieht so aus, als hätten sie infoDictionary geändert, um ein optionales zurückzugeben. Ich habe die Antwort bearbeitet
Connor
116

Schnelle 3/4 Version

func version() -> String {
    let dictionary = Bundle.main.infoDictionary!
    let version = dictionary["CFBundleShortVersionString"] as! String
    let build = dictionary["CFBundleVersion"] as! String
    return "\(version) build \(build)"
} 

Swift 2.x Version

func version() -> String {
    let dictionary = NSBundle.mainBundle().infoDictionary!
    let version = dictionary["CFBundleShortVersionString"] as String
    let build = dictionary["CFBundleVersion"] as String
    return "\(version) build \(build)"
}

wie hier gesehen .

Dan Rosenstark
quelle
1
Sie erhalten den gleichen Schlüssel zweimal, sollten "CFBundleVersion" für die Version verwenden. Ich denke, es ist eine Kopie / Tippfehler in der Vergangenheit :)
für den
Danke @foOg es war ein Tippfehler. Tatsächlich ist es rückwärts: Die kurze ist die Version, die reguläre ist der Build. Seltsam, ich weiß.
Dan Rosenstark
Swift 3 Version. Wenn let infoPath = Bundle.main.path (forResource: "Info.plist", ofType: nil), let infoAttr = try? FileManager.default.attributesOfItem (atPath: infoPath), lassen Sie infoDate = infoAttr [.creationDate] als? Datum {return infoDate} return Date ()
Ryan X
18

Für die endgültige Version von Xcode 6 verwenden

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

Das "?" Zeichen nach infoDictionary ist hier wichtig

JulianM
quelle
1
Verdammt. Ich liebe dieses ganze "optional?, Auspacken!" System, es ist kristallklar und so einfach zu lesen!
Jeroen Bouma
14

Hier ist eine einfache Möglichkeit, Build und Version zu erhalten.

Für 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)
   }

Für Ziel C.

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

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

Lassen Sie mich wissen, wenn ein Problem vorliegt. Das funktioniert bei mir.

Ashu
quelle
13

Swifty Weg AppName, AppVersionund 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
quelle
Warum sollten Sie die Werte auspacken müssen? Meines Wissens ist es unmöglich, dass einer dieser Werte Null ist
Michael
@ Michael einige Leute packen IMMER optionale Werte aus. Einige Leute sagen, du hast recht.
Dan Rosenstark
2
Bundle.mainhatte eine leere infoDictionaryfür mich; Vielleicht, weil ich es innerhalb eines Frameworks mache, nicht einer ausführbaren Datei oder App? Bundle(for: MyClass.self)enthält die erwarteten Werte.
Raphael
7

In Kürze würde ich es als Erweiterung für UIApplication wie folgt machen:

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

Dann können Sie einfach Folgendes verwenden, um alles zu erhalten, was Sie benötigen:

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

// Gibt die Versionsnummer der App zurück

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

// Die Build-Nummer der App zurückgeben

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

Swift 5.0

Ich habe einen Wrapper für Swift 5 erstellt, um einige App-bezogene Zeichenfolgen an einer Stelle in allen meinen Apps mit dem Namen AppInfo abzurufen .

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

Sie können es so verwenden:

print("The apps name = \(AppInfo.appname)")
LukeSideWalker
quelle
Wenn in Swift ein Wert nicht verfügbar ist, wird null verwendet. IMO sollten Sie null anstelle von benutzerdefinierten Platzhalterzeichenfolgen zurückgeben.
Luca Angeletti
Deshalb ist es ein Wrapper: Um immer etwas zurückzubekommen. Die Nullsituation ist nicht wirklich "zerstört", sie ist immer noch da, aber bereits vorbehandelt. Andernfalls müssten Sie die "Null" -Situation an einer anderen Stelle in Ihrer App behandeln.
LukeSideWalker
Danke, Alter. Außerdem befindet sich Ihre letzte geschweifte Klammer außerhalb des Codeblocks. :)
Mark Perkins
2
App-Name kann auch seinCFBundleDisplayName
Gondo
2

Dieser Code funktioniert für Swift 3, Xcode 8:

let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"
Crashalot
quelle
2

Bei Swift 3 wird NSBundle durch Bundle ersetzen, und mainBundle wird einfach durch main ersetzt.

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

[Update: Xcode 6.3.1] Ich habe alle oben genannten Funktionen ausprobiert und keine dieser Funktionen funktioniert in Xcode 6.3.1, aber ich habe festgestellt, dass dies Folgendes bewirkt:

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

Eine weitere Option besteht darin, im AppDelegate die Variablen zu definieren:

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

Dies kann im AppDelegate als Variable bezeichnet werden

user3620768
quelle
0

Swift 3:

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

SWIFT 3 Version

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.
quelle
0

Um ein Ergebnis für das Framework zu erhalten, können Sie es verwenden

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

oder in Tests

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