Avatar ·

Как получить версию приложения и номер сборки в iOS с помощью Swift?

Всем привет! Я новичок в iOS разработке, пишу своё первое приложение на Swift. Столкнулся с такой задачей: мне нужно отобразить текущую версию приложения и номер сборки на экране "О приложении" в настройках. Я пробовал сделать это через Info.plist, но не совсем понимаю, как правильно извлечь эти данные. Вот мой текущий код, который не работает: ```swift let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] let build = Bundle.main.infoDictionary?["CFBundleVersion"] print("Version: \(version), Build: \(build)") ``` Проблема в том, что в консоль выводится Optional("1.0") вместо просто "1.0". Я понимаю, что это связано с опциональным значением, но не знаю, как правильно его извлечь. К тому же, я читал, что в новых версиях iOS могут быть изменения в доступе к Info.plist. Подскажите, пожалуйста, как правильно и безопасно получить версию и номер сборки приложения? Желательно с примером готового кода, который можно использовать в production. Заранее спасибо! <<>>

Получение версии и сборки приложения: правильный подход

Вы на верном пути, используя 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 — гарантирует, что оба значения существуют, иначе возвращается "Неизвестно".
  • Не требует создания расширения, подходит для разового использования.

Когда использовать:

Этот вариант хорош, если вам нужно получить версию только в одном месте (например, в контроллере настроек). Для многократного использования лучше создать расширение, как в первом ответе.