Полное руководство: проверка версии iOS в Objective-C
Изучите полный гайд по проверке версии iOS в Objective-C. Откройте надёжные методы с NSFoundationVersionNumber, корректное сравнение строк версий и лучшие практики.
Как проверить, что версия iOS больше 3.1.3 в Objective‑C?
Я пытаюсь реализовать условную проверку в Objective‑C, чтобы определить, что версия iOS на устройстве больше 3.1.3. Я попробовал использовать:
[[UIDevice currentDevice].systemVersion floatValue]
Однако этот подход не подходит для моих нужд. Я хочу создать простое условное выражение, например:
if (version > 3.1.3) { }
Как правильно сравнивать версии iOS в Objective‑C?
Самый надёжный способ проверить, что версия iOS больше 3.1.3 в Objective‑C — использовать NSFoundationVersionNumber с правильными константами версии, либо [[UIDevice currentDevice] systemVersion] с аккуратным сравнением строк. Однако для iOS 3.1.3 понадобится иной подход, поскольку константы проверки версии, доступные в более новых SDK, тогда ещё не существовали.
Содержание
- Понимание проблемы с сравнение с плавающей точкой
- Использование NSFoundationVersionNumber
- UIDevice SystemVersion с правильным сравнением
- Макросы компиляции для проверки версии iOS
- Лучшие практики проверки версии iOS
Понимание проблемы с сравнение с плавающей точкой
Проблема использования [[UIDevice currentDevice] systemVersion] floatValue напрямую заключается в точности чисел с плавающей точкой и парсинге строк версии. Версии iOS представлены как строки вида «3.1.3», «3.2» или «4.0», но при преобразовании в float возникают несколько проблем:
// Такой подход имеет проблемы с точностью
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, которое не страдает от ошибок точности.
#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, возможно, придётся определить её вручную:
// Если константа не определена автоматически, определяем её сами
#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. Вот надёжный подход:
#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:
#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
- Используйте
NSFoundationVersionNumberдля проверки во время выполнения: это самый надёжный метод для старых версий iOS. - Избегайте прямого сравнения с плавающей точкой: никогда не используйте
[[UIDevice currentDevice] systemVersion] floatValueдля сравнения версий из‑за проблем с точностью. - Используйте правильное сравнение строк: если используете
UIDevice, реализуйте корректный парсинг и сравнение строк версий. - Комбинируйте методы для максимальной совместимости: для современных приложений рассмотрите комбинирование подходов:
+ (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;
}
- Обрабатывайте крайние случаи: подумайте, как ваше приложение должно вести себя с бета‑версиями, сборками разработки и будущими версиями iOS.
Согласно исследованиям из Max’s Programming Notes, комбинация этих подходов обеспечивает наиболее надёжное решение для обнаружения версии iOS в Objective‑C.
Источники
- Как проверить версию iOS? - Stack Overflow
- Как программно определить, какая версия iOS запущена на устройстве? – Max’s Programming Notes
- Правильный способ проверки версии iOS в приложении | Roadfire Software
- NSFoundationVersionNumber в iOS 11 - Как программно определить версию iOS? - Stack Overflow
- Как проверить версию 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 в поддерживаемом диапазоне.