Получение информации о версии и сборке с помощью Swift

92

Я пытаюсь получить доступ к основному NSBundle для получения информации о версии и сборке. Дело в том, что я хочу быстро попробовать, я знаю, как получить его в Objective-C с помощью Build.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];. Но я не знаю, с чего начать с swift, я безуспешно пытался написать его в новом синтаксисе.

Ken-UbiDex
источник
2
Покажите попытки, которые вы уже сделали. Это очень похоже на реализацию Objective-C.
Mick MacCallum
Январь 2017 г. swift 2.3: let sVer = NSBundle.mainBundle (). InfoDictionary? ["CFBundleShortVersionString"] как? Строка let sBuild = NSBundle.mainBundle (). InfoDictionary? ["CFBundleVersion"] как? String self.myVersionLabel.text = String (формат: «Версия% @ Build% @», sVer !, sBuild!)
Мэтью Фергюсон,

Ответы:

167

Что не так с синтаксисом Swift? Кажется, это работает:

if let text = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
    print(text)
}
Коннор
источник
2
Почему это было отклонено? Думаю, это могло бы быть более естественным, letно в остальном это выглядит правильно.
Tommy
Ах, я забыл "as String", чтобы переменная приняла его как строку. Спасибо.
Ken-UbiDex 01
2
Кажется, что это не работает с XCode 6 beta 3
Фредерик Адда
2
Это сработало для меня в Xcode 6 beta 5:let text = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]! as String
Э. Барнс
@Dean Похоже, они изменили infoDictionary, чтобы вернуть необязательный. Я отредактировал ответ
Коннор
118

Версия 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)"
} 

Версия 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)"
}

как видно здесь .

Дэн Розенстарк
источник
1
Вы получаете один и тот же ключ дважды, следует использовать "CFBundleVersion" для версии. Я предполагаю, что это копия / прошедшая опечатка :)
foOg
Спасибо @foOg, это была опечатка. На самом деле все наоборот: короткая - это версия, обычная - это сборка. Странно, я знаю.
Дэн Розенстарк
Версия Swift 3. если let infoPath = Bundle.main.path (forResource: "Info.plist", ofType: nil), пусть infoAttr = try? FileManager.default.attributesOfItem (atPath: infoPath), пусть infoDate = infoAttr [.creationDate] как? Дата {return infoDate} return Date ()
Райан X
18

Для окончательной версии Xcode 6 используйте

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

Знак "?" здесь важен символ после infoDictionary

JulianM
источник
1
Черт. Я действительно люблю всю эту "необязательную? Развернуть!" система, она кристально чистая и легко читается!
Jeroen Bouma
14

Вот простой способ получить сборку и версию.

Для 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)
   }

Для цели C

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

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

Сообщите мне, если возникнут проблемы. Это работает для меня.

Ашу
источник
13

Быстрый способ AppName, AppVersionи 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))."
   }
}
Крис
источник
Зачем вам нужно разворачивать значения? Насколько мне известно, ни одно из этих значений не может быть нулевым
Майкл
@Michael некоторые люди ВСЕГДА разворачивают необязательные значения. Некоторые говорят, что ты прав.
Дэн Розенстарк,
2
Bundle.mainбыл пустой infoDictionaryдля меня; может быть, потому что я делаю это из фреймворка, а не из исполняемого файла или приложения? Bundle(for: MyClass.self)содержит ожидаемые значения.
Рафаэль
7

Я бы быстро сделал это как расширение для UIApplication, например:

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

Тогда вы можете просто использовать следующее, чтобы получить все, что вам нужно:

let version = UIApplication.sharedApplication.applicationVersion() // 1
let build = UIApplication.sharedApplication.applicationBuild() // 80
let both = UIApplication.sharedApplication.versionBuild() // 1(80)
Иржи Тречак
источник
7

// Возвращает номер версии приложения

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

// Возвращаем номер сборки приложения

public static var appBuild: String? {
    return Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
}
Пратюш Пратик
источник
6

Swift 5.0

Я создал оболочку для Swift 5, чтобы получить несколько строк, связанных с приложением, в одном месте во всех моих приложениях под названием 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
     }
}

Вы можете использовать это так:

print("The apps name = \(AppInfo.appname)")
ЛюкСайдУокер
источник
Когда в Swift значение недоступно, используется nil. ИМО, вы должны возвращать nil вместо пользовательских строк-заполнителей.
Лука Анджелетти
Вот почему это обертка: чтобы всегда что-то вернуть. Нулевая ситуация на самом деле не «уничтожена», она все еще существует, но уже предварительно обработана. В противном случае вам пришлось бы обрабатывать ситуацию "nil" в другом месте вашего приложения.
LukeSideWalker
спасибо, приятель. Кроме того, ваша последняя фигурная скобка находится за пределами блока кода. :)
Марк Перкинс
2
имя приложения также может бытьCFBundleDisplayName
gondo
2

Этот код работает для Swift 3, Xcode 8:

let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "0"
let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "0"
Crashalot
источник
2

Для Swift 3 замените NSBundle на Bundle, а mainBundle заменяется просто на main.

let AppVersion = Bundle.main.infoDictionary!["CFBundleVersion"] as! String
Тарика Чавла
источник
1

[Обновление: Xcode 6.3.1] Я пробовал все вышеперечисленное, и ни один из них не работал в Xcode 6.3.1, но я обнаружил, что это работает:

(NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String)!
SunburstEnzo
источник
1

Другой вариант - определить в AppDelegate переменные:

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

на которые можно ссылаться как на переменные в AppDelegate

user3620768
источник
0

Swift 3:

let textVersion
 = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
Звонимир Таслак
источник
0

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()
Райан Икс
источник
0

Чтобы получить результат для фреймворка, вы можете использовать

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

или в тестах

let version = Bundle(for: <SomeClass>.self).infoDictionary?["CFBundleShortVersionString"] as? String
yoAlex5
источник