Другое

Полное руководство: проверка версии iOS в Objective-C

Изучите полный гайд по проверке версии iOS в Objective-C. Откройте надёжные методы с NSFoundationVersionNumber, корректное сравнение строк версий и лучшие практики.

Как проверить, что версия iOS больше 3.1.3 в Objective‑C?

Я пытаюсь реализовать условную проверку в Objective‑C, чтобы определить, что версия iOS на устройстве больше 3.1.3. Я попробовал использовать:

objective-c
[[UIDevice currentDevice].systemVersion floatValue]

Однако этот подход не подходит для моих нужд. Я хочу создать простое условное выражение, например:

objective-c
if (version > 3.1.3) { }

Как правильно сравнивать версии iOS в Objective‑C?

Самый надёжный способ проверить, что версия iOS больше 3.1.3 в Objective‑C — использовать NSFoundationVersionNumber с правильными константами версии, либо [[UIDevice currentDevice] systemVersion] с аккуратным сравнением строк. Однако для iOS 3.1.3 понадобится иной подход, поскольку константы проверки версии, доступные в более новых SDK, тогда ещё не существовали.


Содержание


Понимание проблемы с сравнение с плавающей точкой

Проблема использования [[UIDevice currentDevice] systemVersion] floatValue напрямую заключается в точности чисел с плавающей точкой и парсинге строк версии. Версии iOS представлены как строки вида «3.1.3», «3.2» или «4.0», но при преобразовании в float возникают несколько проблем:

objective‑c
// Такой подход имеет проблемы с точностью
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
// "3.1.3" становится примерно 3.1, теряется патч‑версия
// "11.0" может стать 11.1999998 из‑за арифметики с плавающей точкой

Как отмечено в обсуждении Stack Overflow, преобразование в число с плавающей точкой может дать значения вроде «11.1999998» вместо ожидаемого «11.0».


Использование NSFoundationVersionNumber

Для версий iOS 3.1.3 и ранее NSFoundationVersionNumber является самым надёжным подходом. Он предоставляет целочисленное представление версии iOS, которое не страдает от ошибок точности.

objective‑c
#import <objc/runtime.h>

// Проверяем, что запущено iOS 3.1.3 или новее
if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_3_1_3) {
    // Код для iOS 3.1.3 и новее
} else {
    // Код для iOS 3.1.2 и старее
}

Однако необходимо убедиться, что нужная константа определена. Для iOS 3.1.3, возможно, придётся определить её вручную:

objective‑c
// Если константа не определена автоматически, определяем её сами
#ifndef NSFoundationVersionNumber_iOS_3_1_3
#define NSFoundationVersionNumber_iOS_3_1_3 678.24
#endif

// Затем используем в сравнении
if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_3_1_3) {
    // iOS 3.1.3 или новее
}

Функция floor() критична, так как гарантирует работу с целыми значениями для надёжного сравнения, как рекомендовано в Roadfire Software.


UIDevice SystemVersion с правильным сравнением

Если вы предпочитаете использовать UIDevice, необходимо реализовать правильное сравнение строк версии, а не полагаться на преобразование в float. Вот надёжный подход:

objective‑c
#import <UIKit/UIKit.h>

+ (BOOL)isSystemVersionGreaterThan:(NSString *)versionString {
    NSString *currentVersion = [[UIDevice currentDevice] systemVersion];
    return [currentVersion compare:versionString options:NSNumericSearch] == NSOrderedDescending;
}

// Использование
if ([self isSystemVersionGreaterThan:@"3.1.3"]) {
    // Версия iOS больше 3.1.3
}

Этот метод корректно сравнивает строки версий, учитывая такие случаи, как:

  • «3.1.3» vs «3.1.4» (правильно определяет 3.1.4 как новее)
  • «3.2» vs «3.1.9» (правильно определяет 3.2 как новее)
  • «4.0» vs «3.9.9» (правильно определяет 4.0 как новее)

Опция NSNumericSearch обеспечивает числовое сравнение, а не лексикографическое сравнение строк.


Макросы компиляции для проверки версии iOS

Для проверки версии во время компиляции (полезно в заголовочных файлах, категориях классов или определениях ivar) можно использовать макросы из Availability.h:

objective‑c
#import <Availability.h>

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2
    // Код, требующий iOS 3.2 или новее
#else
    // Код‑fallback для iOS 3.1.3 или старее
#endif

Этот подход работает во время компиляции, а не во время выполнения, что делает его идеальным для условной компиляции. Однако, как отмечено в обсуждении Stack Overflow, этот метод не подходит во всех контекстах, например, для проверки версии во время выполнения.


Лучшие практики проверки версии iOS

  1. Используйте NSFoundationVersionNumber для проверки во время выполнения: это самый надёжный метод для старых версий iOS.
  2. Избегайте прямого сравнения с плавающей точкой: никогда не используйте [[UIDevice currentDevice] systemVersion] floatValue для сравнения версий из‑за проблем с точностью.
  3. Используйте правильное сравнение строк: если используете UIDevice, реализуйте корректный парсинг и сравнение строк версий.
  4. Комбинируйте методы для максимальной совместимости: для современных приложений рассмотрите комбинирование подходов:
objective‑c
+ (BOOL)isIOS313OrLater {
    // Сначала пробуем NSFoundationVersionNumber
    if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_3_1_3) {
        return YES;
    }
    
    // Фолбэк на сравнение строк
    NSString *currentVersion = [[UIDevice currentDevice] systemVersion];
    return [currentVersion compare:@"3.1.3" options:NSNumericSearch] != NSOrderedAscending;
}
  1. Обрабатывайте крайние случаи: подумайте, как ваше приложение должно вести себя с бета‑версиями, сборками разработки и будущими версиями iOS.

Согласно исследованиям из Max’s Programming Notes, комбинация этих подходов обеспечивает наиболее надёжное решение для обнаружения версии iOS в Objective‑C.


Источники

  1. Как проверить версию iOS? - Stack Overflow
  2. Как программно определить, какая версия iOS запущена на устройстве? – Max’s Programming Notes
  3. Правильный способ проверки версии iOS в приложении | Roadfire Software
  4. NSFoundationVersionNumber в iOS 11 - Как программно определить версию iOS? - Stack Overflow
  5. Как проверить версию iOS в вашем приложении - Repeato

Вывод

Чтобы проверить, что версия iOS больше 3.1.3 в Objective‑C, у вас есть несколько надёжных вариантов:

  • Для проверки во время выполнения: используйте NSFoundationVersionNumber с подходящими константами, применяя floor() для целочисленного сравнения.
  • Для сравнения строк: реализуйте правильное сравнение строк версий с опцией NSNumericSearch.
  • Для проверки во время компиляции: используйте препроцессорные макросы из Availability.h.

Самый надёжный подход комбинирует несколько методов, чтобы покрыть разные эпохи iOS и крайние случаи. Избегайте прямого сравнения [[UIDevice currentDevice] systemVersion] как float, особенно при работе с патч‑версиями вроде 3.1.3.

Для поддержки старых версий, таких как 3.1.3, возможно понадобится вручную определить константу версии, если она недоступна в SDK, чтобы ваше приложение корректно определяло и обрабатывало различные версии iOS в поддерживаемом диапазоне.

Авторы
Проверено модерацией
Модерация