Как получить версию приложения и номер сборки в iOS с помощью Swift?
Получение версии и сборки приложения: правильный подход
Вы на верном пути, используя Bundle.main.infoDictionary. Проблема в том, что словарь возвращает опциональные значения, и их нужно корректно извлекать. Вот самый надёжный и распространённый способ:
// MARK: - Версия и сборка приложения
extension Bundle {
var appVersion: String {
return infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0"
}
var buildNumber: String {
return infoDictionary?["CFBundleVersion"] as? String ?? "1"
}
var fullVersion: String {
return "\(appVersion) (\(buildNumber))"
}
}
// Использование
let version = Bundle.main.appVersion
let build = Bundle.main.buildNumber
let full = Bundle.main.fullVersion
print("Версия: \(version), Сборка: \(build)") // Версия: 1.0, Сборка: 1
Объяснение кода:
- Расширение Bundle — добавляет удобные свойства к стандартному классу Bundle.
- infoDictionary? — опциональный словарь. Если его нет, вернётся значение по умолчанию.
- as? String — безопасное приведение типа. Если значение не строка, вернётся nil.
- ?? "1.0" — оператор объединения с nil. Если всё пошло не так, используем запасное значение.
Почему это важно?
В production-коде нельзя полагаться на то, что Info.plist всегда содержит нужные ключи. Например:
- При тестировании через XCTest словарь может быть пустым.
- В некоторых конфигурациях сборки (например, Debug) ключи могут отсутствовать.
- Apple может изменить структуру Info.plist в будущих версиях iOS.
Альтернативный вариант (для iOS 16+):
Начиная с iOS 16, появился новый способ через Bundle.main.infoDictionary, но с улучшенной типизацией:
if #available(iOS 16.0, *) {
let version = Bundle.main.infoDictionary?[.appVersion] as? String ?? "1.0"
let build = Bundle.main.infoDictionary?[.buildVersion] as? String ?? "1"
} else {
// Используйте старый метод
}
Проверка в Info.plist:
Убедитесь, что в вашем проекте (файл Info.plist или Project > Target > General) заполнены поля:
- Version (CFBundleShortVersionString) — отображаемая версия, например "2.4.1".
- Build (CFBundleVersion) — номер сборки, например "42".
Этот код подходит для Swift 5+ и всех версий iOS (начиная с iOS 9). Используйте его в production без опасений.
<<Более простой способ (без расширения)
Если вам не нужно переиспользовать код в нескольких местах, можно обойтись простой функцией:
func getAppVersion() -> String {
guard let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String,
let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String else {
return "Неизвестно"
}
return "\(version) (\(build))"
}
// Использование
let versionInfo = getAppVersion()
print(versionInfo) // "1.0 (1)"
Отличие от первого ответа:
- object(forInfoDictionaryKey:) — более старый, но всё ещё рабочий метод.
- guard let — гарантирует, что оба значения существуют, иначе возвращается "Неизвестно".
- Не требует создания расширения, подходит для разового использования.
Когда использовать:
Этот вариант хорош, если вам нужно получить версию только в одном месте (например, в контроллере настроек). Для многократного использования лучше создать расширение, как в первом ответе.