У меня есть приложение IOS с серверной частью Azure, и я хотел бы регистрировать определенные события, например, имена входа и какие версии пользователей приложения работают.
Как я могу вернуть версию и номер сборки, используя Swift?
У меня есть приложение IOS с серверной частью Azure, и я хотел бы регистрировать определенные события, например, имена входа и какие версии пользователей приложения работают.
Как я могу вернуть версию и номер сборки, используя Swift?
Ответы:
РЕДАКТИРОВАТЬ
Обновлено для Swift 4.2
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
РЕДАКТИРОВАТЬ
Как указал @azdev в новой версии Xcode, вы получите ошибку компиляции при попытке использовать мое предыдущее решение, чтобы решить эту проблему, просто отредактируйте его, как предложено, чтобы развернуть словарь пакета, используя!
let nsObject: AnyObject? = Bundle.main.infoDictionary!["CFBundleShortVersionString"]
Конец Править
Просто используйте ту же логику, что и в Objective-C, но с небольшими изменениями
//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
Я надеюсь, что это помогает вам.
Дэвид
infoDictionary
должен быть развернут с помощью !
. Это то, что я использую, помещено в файл Globals.swift:let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as String
let appVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Я знаю, что на это уже ответили, но лично я думаю, что это немного чище:
Swift 3.0:
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
Свифт <2.3
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
self.labelVersion.text = version
}
Таким образом, версия if let заботится об условной обработке (в моем случае задает текст метки), и если infoDictionary или CFBundleShortVersionString равны нулю, необязательное развертывание приведет к пропуску кода.
self.labelVersion.text
является необязательным типом, так что вы можете напрямую назначитьNSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String
let
, просто интересно, зачем это нужно. Спасибо!
Обновлено для Swift 3.0
В NS
-prefixes теперь ушли в Swift 3.0 и некоторые свойства / методы изменились имена более Swifty. Вот как это выглядит сейчас:
extension Bundle {
var releaseVersionNumber: String? {
return infoDictionary?["CFBundleShortVersionString"] as? String
}
var buildVersionNumber: String? {
return infoDictionary?["CFBundleVersion"] as? String
}
}
Bundle.main.releaseVersionNumber
Bundle.main.buildVersionNumber
Старый обновленный ответ
Со времени моего первоначального ответа я много работал с Frameworks, поэтому я хотел обновить свое решение до чего-то более простого и гораздо более полезного в среде с несколькими пакетами:
extension NSBundle { var releaseVersionNumber: String? { return self.infoDictionary?["CFBundleShortVersionString"] as? String } var buildVersionNumber: String? { return self.infoDictionary?["CFBundleVersion"] as? String } }
Теперь это расширение будет полезно в приложениях для идентификации как основного пакета, так и любых других включенных пакетов (таких как общая платформа для программирования расширений или третьи платформы, такие как AFNetworking), например, так:
NSBundle.mainBundle().releaseVersionNumber NSBundle.mainBundle().buildVersionNumber // or... NSBundle(URL: someURL)?.releaseVersionNumber NSBundle(URL: someURL)?.buildVersionNumber
Оригинальный ответ
Я хотел бы улучшить некоторые из ответов, уже опубликованных. Я написал расширение класса, которое может быть добавлено в вашу цепочку инструментов для более логичной обработки.
extension NSBundle { class var applicationVersionNumber: String { if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"]
в виде? String {return version} return "Номер версии недоступен"}
class var applicationBuildNumber: String { if let build = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String { return build } return "Build Number Not Available" } }
Так что теперь вы можете легко получить к нему доступ:
let versionNumber = NSBundle.applicationVersionNumber
Я также знаю, что на это уже ответили, но я обернул предыдущие ответы:
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")"
}
}
Применение:
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
}
Для более старых версий :
class func getVersion() -> String {
if let version = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as? String {
return version
}
return "no version info"
}
Так что если вы хотите установить текст метки или хотите использовать где-то еще;
self.labelVersion.text = getVersion()
Для Swift 4.0
let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"]!
let build = Bundle.main.infoDictionary!["CFBundleVersion"]!
Я сделал расширение на Bundle
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
}
}
а затем использовать его
versionLabel.text = "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"
Для Swift 3.0 NSBundle не работает, следующий код работает отлично.
let versionNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
as! String
и только для номера сборки это:
let buildNumberString =
Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")
as! String
Смущает, что 'CFBundleVersion' - это номер сборки, введенный в Xcode в General-> Identity.
Xcode 9.4.1 Swift 4.1
Обратите внимание на использование localizedInfoDictionary для выбора правильной языковой версии отображаемого имени пакета.
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, полезное расширение для 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
}
}
Применение:
someLabel.text = Bundle.main.versionNumber
ОП запросил как номер версии, так и номер сборки. К сожалению, большинство ответов не предоставляют оба этих варианта. Кроме того, другие добавляют ненужные методы расширения. Вот тот, который довольно прост и решает проблему ОП:
// 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 ""
}
}
Мой ответ (по состоянию на август 2015 года), учитывая, что Свифт продолжает развиваться:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Я создал расширение для 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"
}
}
Посмотрев на документацию, я считаю, что следующее чище:
let version =
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString")
as? String
Источник : «Использование этого метода предпочтительнее других методов доступа, потому что он возвращает локализованное значение ключа, когда он доступен».
Для Swift 1.2 это:
let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String
let build = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
Свифт 3:
Номер версии
if let versionNumberString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { // do something }
Номер сборки
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"]
Быстрый старый синтаксис
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
}
}
Внимание: вы должны использовать if let здесь, если не установлена версия или сборка приложения, что приведет к падению, если вы попытаетесь использовать! развернуть.
Вот обновленная версия для 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
// Сначала получаем nsObject, определяя как необязательный AnyObject
let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject
// Затем просто приведем объект в виде String, но будьте осторожны, вы можете перепроверить ноль
let version = nsObject as! String
для всех, кто интересуется, есть хорошая и аккуратная библиотека, SwifterSwift
доступная на github, а также полностью документированная для каждой версии swift (см. swifterswift.com ).
Используя эту библиотеку, читать версию приложения и номер сборки так же просто, как это:
import SwifterSwift
let buildNumber = SwifterSwift.appBuild
let version = SwifterSwift.appVersion
вот функция, которую я использую, чтобы решить, показывать ли страницу "приложение обновлено" или нет. Он возвращает номер сборки, который я преобразую в 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")
}
Если никогда не использовался раньше, он вернет 0, который меньше текущего номера сборки. Чтобы не показывать такой экран новым пользователям, просто добавьте номер сборки после первого входа в систему или после завершения регистрации.
Простая служебная функция для возврата версии приложения как 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)
Я объединил идеи из нескольких ответов и немного расширил:
Фонд импорта
Bundle extension {
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 пример использования
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)"
}