Как проверить версию osx во время компиляции? [Дубликат]

Простыми словами ... Если я пишу новый класс Swimmer для добавления функциональности swim () и вам нужно использовать объект класса say Dog, и этот класс Dog реализует интерфейс Animal, который объявляет swim () [To лучше понять ... вы можете нарисовать диаграмму о том, о чем я говорю]. В верхней части иерархии (Animal) он очень абстрактный, а внизу (Dog) он очень конкретный. То, как я думаю о «программировании для интерфейсов», заключается в том, что, когда я пишу класс Swimmer, я хочу написать свой код против интерфейса, который находится так далеко от иерархии, которая в этом случае является объектом Animal. Интерфейс свободен от деталей реализации и, таким образом, делает ваш код слабосвязанным. Детали реализации могут быть изменены со временем, однако это не повлияет на оставшийся код, поскольку все, с чем вы взаимодействуете, связано с интерфейсом, а не с реализацией. Вам все равно, что такое реализация ... все, что вы знаете, это то, что будет класс, который будет реализовывать интерфейс.

792
задан James Webster 7 August 2015 в 13:42
поделиться

30 ответов

Быстрый ответ ...

С Swift 2.0 вы можете использовать #available в if или guard для защиты кода, который должен запускаться только в определенных системах.

if #available(iOS 9, *) {} В Objective-C вам нужно проверить версию системы и выполнить сравнение.

[[NSProcessInfo processInfo] operatingSystemVersion] в iOS 8 и выше.

Начиная с Xcode 9 :

if (@available(iOS 9, *)) {}

Полный ответ ...

В Objective-C и Swift в редких случаях лучше избегайте использования версии операционной системы в качестве индикатора возможностей устройства или ОС. Обычно существует более надежный метод проверки доступности конкретной функции или класса.

Проверка наличия API-интерфейсов:

Например, вы можете проверить, есть ли UIPopoverController доступный на текущем устройстве с помощью NSClassFromString:

if (NSClassFromString(@"UIPopoverController")) {
    // Do something
}

Для слабосвязанных классов, можно безопасно сразу передать сообщение классу. Примечательно, что это работает для фреймворков, которые явно не связаны как «Обязательно». Для отсутствующих классов выражение оценивается как nil, если не выполняется условие:

if ([LAContext class]) {
    // Do something
}

Некоторые классы, такие как CLLocationManager и UIDevice, предоставляют методы проверки возможностей устройства:

if ([CLLocationManager headingAvailable]) {
    // Do something
}

Проверка наличия символов:

Очень часто вы должны проверить наличие константы. Это появилось в iOS 8 с введением UIApplicationOpenSettingsURLString, который использовался для загрузки настроек приложения через -openURL:. Значение не существовало до iOS 8. Передача nil в этот API приведет к сбою, поэтому сначала вы должны убедиться в наличии константы:

if (&UIApplicationOpenSettingsURLString != NULL) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}

Сравнение с версией операционной системы:

Предположим, вы столкнулись с относительно редкой необходимостью проверить версию операционной системы. Для проектов, ориентированных на iOS 8 и выше, NSProcessInfo включает метод сравнения версий с меньшей вероятностью ошибки:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Проекты, ориентированные на более старые системы, могут использовать systemVersion в UIDevice. Apple использует его в своем образном коде GLSprite .

// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) {
    displayLinkSupported = TRUE;
}

Если по какой-либо причине вы решите, что systemVersion - это то, что вы хотите, обязательно обработайте его как строку или вы рискуете усечь номер версии исправления (например, 3.1.2 -> 3.1).

908
ответ дан nathan 23 August 2018 в 02:43
поделиться
  • 1
    Существуют конкретные случаи, когда проверка на версию системы оправдана. Например, несколько классов и методов, которые были private n 3.x, были опубликованы в 4.0, поэтому, если вы просто проверили их доступность, вы получите неверный результат в 3.x. Кроме того, способ, которым UIScrollViews обрабатывает масштаб масштабирования, тонко изменен в 3.2 и выше, поэтому вам нужно будет проверить версии ОС, чтобы обработать результаты соответствующим образом. – Brad Larson♦ 27 July 2010 в 05:03
  • 2
    Хорошее разъяснение, спасибо. – Justin 31 July 2010 в 18:49
  • 3
    iOS 3.2 не отправляет -viewWillAppear в UISplitViewController. Мой взлом - это определить, iOS 4.0, и отправить его в контроллер подробного просмотра самостоятельно в корневом представлении -didSelectRowAtIndexPath. – jww 17 July 2011 в 10:36
  • 4
    Вы должны быть немного осторожны здесь, потому что [@"10.0" compare:@"10" options:NSNumericSearch] возвращает NSOrderedDescending, что вполне может не предназначаться вообще. (Я мог бы ожидать NSOrderedSame.) Это, по крайней мере, теоретическая возможность. – SK9 10 December 2011 в 11:51
  • 5
    – Hot Licks 15 March 2013 в 19:01
  • 6
    С введением TVos это даже стало более важным. Смотрите, как TVos вернет 9.0, в то время как используется 9.1 SDK. Поэтому лучше проверить класс или метод (селектор), после чего вы должны проверить NSFoundationVersionNumber , и только если это невозможно, проверьте версии системы на UIDevice. – rckoenes 3 November 2015 в 16:13

Как было предложено официальными документами Apple docs : вы можете использовать NSFoundationVersionNumber из файла заголовка NSObjCRuntime.h.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}
245
ответ дан CarlJ 23 August 2018 в 02:43
поделиться
  • 1
    +1 На самом деле это самый безопасный и самый точный вариант здесь. – mxcl 11 September 2013 в 19:10
  • 2
    Um .. NSFoundationVersionNumber_iOS_6_1 не существует в SDK iOS 5. – Kjuly 22 September 2013 в 02:59
  • 3
    и если есть обновление iOS 6.2 один день? – Cœur 2 October 2013 в 09:53
  • 4
    нет, вы ошибаетесь, NSFoundationVersionNumber_iOS_7_0 не существует. Но хорошо, мы могли бы определить его с помощью #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Чтобы этого не случилось, я пошел с макросом SYSTEM_VERSION_LESS_THAN (v) из yasirmturk – Cœur 2 October 2013 в 15:05
  • 5
    nope, но apple добавит NSFoundationVersionNumber_iOS_8_0 в iOS 9. просто проверьте NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1 – CarlJ 19 September 2014 в 09:55

Я знаю, что это старый вопрос, но кто-то должен был упомянуть макросы времени компиляции в Availability.h. Все остальные методы здесь - это временные решения и не будут работать в файле заголовка, классе или определении ivar.

Для этих ситуаций используйте

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_6_0
  // iOS 6+ code here
#else
  // Pre iOS 6 code here
#endif

h / t этот ответ

19
ответ дан Community 23 August 2018 в 02:43
поделиться
  • 1
    Хм, нет. Это неправильно в нескольких важных аспектах. 1: Номера версий не всегда являются простым числом с плавающей запятой, например "4.2.1" является допустимым номером версии iOS. 2: Вы выполняете сравнение с плавающей точкой. Из-за конечной точности чисел с плавающей запятой ваше сравнение может потерпеть неудачу (или преуспеть), если вы этого не ожидали. – Mac 2 July 2012 в 05:11
  • 2
    И самая проклятая причина, 3: Номера Float имеют различный порядок, чем строки: 4.10 < 4.2, но "4.10" > "4.2". – yakovlev 22 August 2012 в 21:02
  • 3
    еще больше осуждать? [@ & Quot; x.y.z & Quot; floatValue] возвращает x.y, поэтому 3.1.3 всегда будет возвращать 3.1, а не 3.13. – Vitali 30 November 2012 в 04:47
  • 4
    Строки могут иметь различный порядок, который плавает, но «4.10». & Lt; & Quot; 4,2 & Quot ;. – pzulw 11 July 2013 в 17:54

Запуск Xcode 9 в Objective-C:

if (@available(iOS 11, *)) {
    // iOS 11 (or newer) ObjC code
} else {
    // iOS 10 or older code
}

Запуск Xcode 7 в Swift:

if #available(iOS 11, *) {
    // iOS 11 (or newer) Swift code
} else {
    // iOS 10 or older code
}

Для версии вы можете указать MAJOR, MINOR или PATCH (см. http://semver.org/ для определений). Примеры:

  • iOS 11 и iOS 11.0 - одна и та же минимальная версия
  • iOS 10, iOS 10.3, iOS 10.3.1 - разные минимальные версии

Вы можете вводить значения для любой из этих систем:

  • iOS, macOS, watchOS, tvOS

Пример реального случая, взятый из одного из моих модулей :

if #available(iOS 10.0, tvOS 10.0, *) {
    // iOS 10+ and tvOS 10+ Swift code
} else {
    // iOS 9 and tvOS 9 older code
}

документация

64
ответ дан Cœur 23 August 2018 в 02:43
поделиться
  • 1
    Как это можно инвертировать в Objective-C или Swift? – Legoless 19 September 2017 в 14:41
  • 2
    @Legoless if (...) {} else { ... } – Cœur 19 September 2017 в 15:43
  • 3
    Могу ли я использовать guard в Objective-C вместо того, чтобы оставить блок открытым и отступом в инструкции else? – Legoless 19 September 2017 в 15:44
  • 4
    @Legoless нет, просто используйте пустой блок if, а затем else. – Cœur 19 September 2017 в 15:45
  • 5
    Это решение, которое я сейчас имею, просто хотел избежать ненужных отступов и пустых блоков if. – Legoless 19 September 2017 в 15:54

Предпочтительный подход

В Swift 2.0 Apple добавила проверку доступности с использованием гораздо более удобного синтаксиса (подробнее здесь ). Теперь вы можете проверить версию ОС с помощью более чистого синтаксиса:

if #available(iOS 9, *) {
    // Then we are on iOS 9
} else {
    // iOS 8 or earlier
}

Это предпочтительная проверка respondsToSelector и т. Д. ( Что нового в Swift ). Теперь компилятор всегда предупреждает вас, если вы не охраняете свой код должным образом.


Pre Swift 2.0

Новое в iOS 8 - NSProcessInfo, позволяющее улучшить семантическое управление версиями проверки.

Развертывание на iOS 8 и выше

Для минимальных целей развертывания iOS 8.0 или выше используйте NSProcessInfo operatingSystemVersion или isOperatingSystemAtLeastVersion.

Это даст следующее:

let minimumVersion = NSOperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2)
if NSProcessInfo().isOperatingSystemAtLeastVersion(minimumVersion) {
    //current version is >= (8.1.2)
} else {
    //current version is < (8.1.2)
}

Развертывание на iOS 7

Для минимальных целей развертывания iOS 7.1 или ниже , используйте сравнение с NSStringCompareOptions.NumericSearch на UIDevice systemVersion.

Это даст:

let minimumVersionString = "3.1.3"
let versionComparison = UIDevice.currentDevice().systemVersion.compare(minimumVersionString, options: .NumericSearch)
switch versionComparison {
    case .OrderedSame, .OrderedDescending:
        //current version is >= (3.1.3)
        break
    case .OrderedAscending:
        //current version is < (3.1.3)
        fallthrough
    default:
        break;
}

Подробнее читается в NSHipster .

34
ответ дан Daniel Galasko 23 August 2018 в 02:43
поделиться

немного опоздал на сторону, но в свете iOS 8.0, это может быть актуально:

, если вы можете избежать использования

[[UIDevice currentDevice] systemVersion]

Вместо этого проверьте наличие метода / класса / любого другого.

if ([self.yourClassInstance respondsToSelector:@selector(<yourMethod>)]) 
{ 
    //do stuff 
}

Я нашел его полезным для менеджера местоположений, где мне нужно вызвать requestWhenInUseAuthorization для iOS 8.0, но этот метод недоступен для iOS & lt; 8

4
ответ дан Denis Kanygin 23 August 2018 в 02:43
поделиться
  • 1
    Я думаю, что это хорошее решение для многих случаев – Ferran Maylinch 15 June 2015 в 19:27

Пример Swift, который действительно работает:

switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
case .OrderedSame, .OrderedDescending:
    println("iOS >= 8.0")
case .OrderedAscending:
    println("iOS < 8.0")
}

Не используйте NSProcessInfo, потому что он не работает под 8.0, поэтому его почти бесполезно до 2016 года

0
ответ дан Esqarrouth 23 August 2018 в 02:43
поделиться
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
1
ответ дан Gank 23 August 2018 в 02:43
поделиться
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

if (_kisiOS7) {
            NSLog(@"iOS7 or greater")
} 
else {
           NSLog(@"Less than iOS7");
}
3
ответ дан Gaurav Gilani 23 August 2018 в 02:43
поделиться
float deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
float versionToBeCompared = 3.1.3; //(For Example in your case)

if(deviceOSVersion < versionToBeCompared)
   //Do whatever you need to do. Device version is lesser than 3.1.3(in your case)
else 
   //Device version should be either equal to the version you specified or above
0
ответ дан GJDK 23 August 2018 в 02:43
поделиться

Новый способ проверить версию системы с помощью быстрого Forget [[UIDevice currentDevice] systemVersion] и NSFoundationVersionNumber.

Мы можем использовать NSProcessInfo -isOperatingSystemAtLeastVersion

     import Foundation

     let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
     NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
5
ответ дан iGo 23 August 2018 в 02:43
поделиться

Только для получения значения строки версии ОС:

[[UIDevice currentDevice] systemVersion]
2
ответ дан itsji10dra 23 August 2018 в 02:43
поделиться

В качестве вариации решения yasimturks я определил одну функцию и несколько значений enum вместо пяти макросов.

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

if (systemVersion(LessThan, @"5.0")) ...

.h файл:

typedef enum {
  LessThan,
  LessOrEqual,
  Equal,
  GreaterOrEqual,
  GreaterThan,
  NotEqual
} Comparison;

BOOL systemVersion(Comparison test, NSString* version);

.m файл:

BOOL systemVersion(Comparison test, NSString* version) {
  NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare: version options: NSNumericSearch];
  switch (test) {
    case LessThan:       return result == NSOrderedAscending;
    case LessOrEqual:    return result != NSOrderedDescending;
    case Equal:          return result == NSOrderedSame;
    case GreaterOrEqual: return result != NSOrderedAscending;
    case GreaterThan:    return result == NSOrderedDescending;
    case NotEqual:       return result != NSOrderedSame;
  }
}

Вы должны добавить префикс вашего приложения к именам, особенно к типу Comparison.

1
ответ дан jcsahnwaldt 23 August 2018 в 02:43
поделиться

Попробуйте:

NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"3.1.3" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending) {
    // OS version >= 3.1.3
} else {
    // OS version < 3.1.3
}
36
ответ дан Jonathan Grynspan 23 August 2018 в 02:43
поделиться
  • 1
    Почему бы не изменить порядок здесь и сохранить сравнение, так как оба @ "3.1.3" и systemVersion - это NSStrings? Т.е.: if ([@ "3.1.3" сравнение: [UIDevice currentDevice] .systemVersion: NSNumericSearch] == NSOrderedDescending); // версия ОС & gt; = 3.1.3 else; // версия ОС & lt; 3.1.3` – Rob 12 May 2012 в 22:35
  • 2
    Это может сделать логику менее ясной. Однако операция должна быть эквивалентной. – Jonathan Grynspan 13 May 2012 в 09:23
  • 3
    Сравнение двух целых чисел, конечно, не очень дорого. – KPM 30 July 2012 в 15:32
  • 4
    Это действительно вопрос стиля. Накладные расходы на отправку сообщений значительно перевешивают дополнительное целочисленное сравнение. – Jonathan Grynspan 30 July 2012 в 15:52

Решение для проверки версии iOS в Swift

switch (UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)) {
    case .OrderedAscending:
       println("iOS < 8.0")

    case .OrderedSame, .OrderedDescending:
       println("iOS >= 8.0")
}

Con этого решения: это просто плохая практика, чтобы проверять номера версий ОС, в зависимости от того, как вы это делаете. Поэтому никогда не следует жестко привязывать кодовые зависимости, всегда проверяйте возможности, возможности или существование класса. Учти это; Apple может выпускать обратно совместимую версию класса, если они это сделали, то код, который вы предлагаете, никогда не будет использовать его, поскольку ваша логика ищет номер версии ОС и НЕ существование класса.

( Источник этой информации )

Решение для проверки существования класса в Swift

if (objc_getClass("UIAlertController") == nil) {
   // iOS 7
} else {
   // iOS 8+
}

Не используйте if (NSClassFromString("UIAlertController") == nil), потому что он корректно работает на симуляторе iOS, используя iOS 7.1 и 8.2, но если вы протестируете на реальном устройстве с использованием iOS 7.1, вы, к сожалению, заметите, что никогда не будете проходить через часть фрагмента кода.

1
ответ дан King-Wizard 23 August 2018 в 02:43
поделиться
  • 1
    Зачем голосовать? Это решение отлично работает с использованием Swift и любой версии iOS. Особенно проверяется существование класса. – King-Wizard 6 April 2015 в 12:03
+(BOOL)doesSystemVersionMeetRequirement:(NSString *)minRequirement{

// eg  NSString *reqSysVer = @"4.0";


  NSString *currSysVer = [[UIDevice currentDevice] systemVersion];

  if ([currSysVer compare:minRequirement options:NSNumericSearch] != NSOrderedAscending)
  {
    return YES;
  }else{
    return NO;
  }


}
6
ответ дан kleopatra 23 August 2018 в 02:43
поделиться
  • 1
    это хорошо работает, игнорирует все десятичные точки. – Jef 20 November 2012 в 14:27
  • 2
    Прекрасно работает!! TY – DZenBot 12 December 2012 в 17:52
  • 3
    @Jef Периоды не являются десятичными точками в управлении версиями и имеют значение. Ваш ответ не игнорирует периоды, он потерпит неудачу, если это произойдет. В версировании каждый период, выделенный элементом, является полным числом. Пример: «1.23.45» больше, чем «1.2.345», поскольку второй элемент «23» больше, чем «2». Если вы устраните периоды, это будет одинаковое число. – Andres Canella 7 July 2015 в 23:09

Попробуйте

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { 
// do some work
}
0
ответ дан Muhammad Aamir Ali 23 August 2018 в 02:43
поделиться
  • 1
    Объясните, что это делает. – Kevin Panko 3 April 2014 в 15:29
  • 2
    если проверит, является ли версия os ios 7 или нет – Muhammad Aamir Ali 3 April 2014 в 15:31

Есть версия вроде 7.0 или 6.0.3, поэтому мы можем просто конвертировать версию в число для сравнения. если версия похожа на 7.0, просто добавьте к ней еще один «.0», а затем возьмите его числовое значение.

 int version;
 NSString* iosVersion=[[UIDevice currentDevice] systemVersion];
 NSArray* components=[iosVersion componentsSeparatedByString:@"."];
 if ([components count]==2) {
    iosVersion=[NSString stringWithFormat:@"%@.0",iosVersion];

 }
 iosVersion=[iosVersion stringByReplacingOccurrencesOfString:@"." withString:@""];
 version=[iosVersion integerValue];

Для 6.0.0

  if (version==600) {
    // Do something
  }

для 7.0

 if (version==700) {
   // Do something
 }
2
ответ дан NaXir 23 August 2018 в 02:43
поделиться
  • 1
    простое удаление десятичных точек - неправильный подход. рассмотрим компонент длиной более 1 символа, например. 6.1.10. то этот алгоритм даст 6110 > 700, что неверно. – ardnew 26 January 2017 в 22:33
  • 2
    Я понимаю, что яблоко плохо развивает новые версии, но в большинстве случаев второе число версии не выходит за пределы 5, поэтому 10 не может быть и речи. Это подход adhoc, поэтому, если он обрабатывает регистр для двух компонентов, вы можете его модифицировать, чтобы обрабатывать четыре case aswel, если вы хотите сделать это вручную. Во всяком случае, этот подход был прокомментирован во время iOS6 или 7. iOS 9 и 10 имеют гораздо лучшие способы проверки его i-e #доступным. – NaXir 27 January 2017 в 05:17

UIDevice + IOSVersion.h

@interface UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion

@end

UIDevice + IOSVersion.m

#import "UIDevice+IOSVersion.h"

@implementation UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedSame;
}

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

+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedDescending;
}

@end
5
ответ дан Oliver Pearmain 23 August 2018 в 02:43
поделиться
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

Где, конечно, NSFoundationVersionNumber_iOS_6_1 необходимо изменить, применив для версии iOS, которую вы хотите проверить. То, что я сейчас написал, вероятно, будет много использовано при тестировании, если устройство работает под управлением iOS7 или предыдущей версии.

4
ответ дан OscarWyck 23 August 2018 в 02:43
поделиться

Попробуйте приведенный ниже код:

NSString *versionString = [[UIDevice currentDevice] systemVersion];
2
ответ дан Praveen 23 August 2018 в 02:43
поделиться

Я всегда сохраняю их в файле Constants.h:

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES) 
#define IS_OS_5_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)
#define IS_OS_6_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
#define IS_OS_8_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
8
ответ дан Segev 23 August 2018 в 02:43
поделиться
  • 1
    Отлично. Лучше разместить это в файле .pch вашего проекта XCode – Vaibhav Jhaveri 3 April 2015 в 04:51
  • 2
    Я помещаю все мои константы в свой файл Constants.h, который импортируется в мой файл pch. – Segev 3 April 2015 в 07:27

В общем, лучше спросить, может ли объект выполнить данный селектор, а не проверять номер версии, чтобы решить, должен ли он присутствовать.

Если это не вариант, вам нужно будьте немного осторожны, потому что [@"5.0" compare:@"5" options:NSNumericSearch] возвращает NSOrderedDescending, который вообще не может быть предназначен; Я мог бы ожидать здесь NSOrderedSame. Это, по крайней мере, теоретическая проблема, на которую, по моему мнению, стоит защищаться.

Также стоит подумать о возможности ввода плохой версии, с которой нельзя разумно сравнить. Apple поставляет три предопределенные константы NSOrderedAscending, NSOrderedSame и NSOrderedDescending, но я могу подумать об использовании для некоторой вещи, названной NSOrderedUnordered, в случае, если я не могу сравнивать две вещи, и я хочу вернуть значение, указывающее это .

Более того, не исключено, что Apple когда-нибудь расширит свои три предопределенные константы, чтобы обеспечить множество возвращаемых значений, делая сравнение != NSOrderedAscending неразумным.

, рассмотрим следующий код.

typedef enum {kSKOrderedNotOrdered = -2, kSKOrderedAscending = -1, kSKOrderedSame = 0, kSKOrderedDescending = 1} SKComparisonResult;

@interface SKComparator : NSObject
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo;
@end

@implementation SKComparator
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo {
  if (!vOne || !vTwo || [vOne length] < 1 || [vTwo length] < 1 || [vOne rangeOfString:@".."].location != NSNotFound ||
    [vTwo rangeOfString:@".."].location != NSNotFound) {
    return SKOrderedNotOrdered;
  }
  NSCharacterSet *numericalCharSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
  NSString *vOneTrimmed = [vOne stringByTrimmingCharactersInSet:numericalCharSet];
  NSString *vTwoTrimmed = [vTwo stringByTrimmingCharactersInSet:numericalCharSet];
  if ([vOneTrimmed length] > 0 || [vTwoTrimmed length] > 0) {
    return SKOrderedNotOrdered;
  }
  NSArray *vOneArray = [vOne componentsSeparatedByString:@"."];
  NSArray *vTwoArray = [vTwo componentsSeparatedByString:@"."];
  for (NSUInteger i = 0; i < MIN([vOneArray count], [vTwoArray count]); i++) {
    NSInteger vOneInt = [[vOneArray objectAtIndex:i] intValue];
    NSInteger vTwoInt = [[vTwoArray objectAtIndex:i] intValue];
    if (vOneInt > vTwoInt) {
      return kSKOrderedDescending;
    } else if (vOneInt < vTwoInt) {
      return kSKOrderedAscending;
    }
  }
  if ([vOneArray count] > [vTwoArray count]) {
    for (NSUInteger i = [vTwoArray count]; i < [vOneArray count]; i++) {
      if ([[vOneArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedDescending;
      }
    }
  } else if ([vOneArray count] < [vTwoArray count]) {
    for (NSUInteger i = [vOneArray count]; i < [vTwoArray count]; i++) {
      if ([[vTwoArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedAscending;
      }
    }
  }
  return kSKOrderedSame;
}
@end
4
ответ дан SK9 23 August 2018 в 02:43
поделиться

С классом версии, который содержится в проекте nv-ios-version (версия Apache, версия 2.0), легко получить и сравнить версию iOS. Ниже приведен пример кода сбрасывает версию iOS и проверяет, больше или меньше версии 6.0.

// Get the system version of iOS at runtime.
NSString *versionString = [[UIDevice currentDevice] systemVersion];

// Convert the version string to a Version instance.
Version *version = [Version versionWithString:versionString];

// Dump the major, minor and micro version numbers.
NSLog(@"version = [%d, %d, %d]",
    version.major, version.minor, version.micro);

// Check whether the version is greater than or equal to 6.0.
if ([version isGreaterThanOrEqualToMajor:6 minor:0])
{
    // The iOS version is greater than or equal to 6.0.
}

// Another way to check whether iOS version is
// greater than or equal to 6.0.
if (6 <= version.major)
{
    // The iOS version is greater than or equal to 6.0.
}

Страница проекта: nv-ios-версия TakahikoKawasaki / nv-ios-version

Блог: получить и сравнить версию iOS во время исполнения с классом версии Получить и сравнить версию iOS во время выполнения с классом версии

6
ответ дан Sujania 23 August 2018 в 02:43
поделиться
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Затем добавьте условие if: -

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
   //Your code
}       
3
ответ дан Sumit Kumar Saha 23 August 2018 в 02:43
поделиться

Это используется для проверки совместимости версии SDK в Xcode, это если у вас большая команда с разными версиями Xcode или нескольких проектов, поддерживающих разные SDK, которые используют один и тот же код:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
  //programming in iOS 8+ SDK here
#else
  //programming in lower than iOS 8 here   
#endif

Вы действительно хотите проверить версию iOS на устройстве. Вы можете сделать это с помощью этого:

if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
  //older than iOS 8 code here
} else {
  //iOS 8 specific code here
}

Swift version:

if let version = Float(UIDevice.current.systemVersion), version < 9.3 {
    //add lower than 9.3 code here
} else {
    //add 9.3 and above code here
}
34
ответ дан Travis M. 23 August 2018 в 02:43
поделиться

Используя рекомендуемый способ ... если в файлах заголовков нет определения, вы всегда можете распечатать его на консоли с помощью устройства желаемой версии IOS.

- (BOOL) isIOS8OrAbove{
    float version802 = 1140.109985;
    float version8= 1139.100000; // there is no def like NSFoundationVersionNumber_iOS_7_1 for ios 8 yet?
    NSLog(@"la version actual es [%f]", NSFoundationVersionNumber);
    if (NSFoundationVersionNumber >= version8){
        return true;
    }
    return false;
}
1
ответ дан tyoc213 23 August 2018 в 02:43
поделиться

Более общая версия в Obj-C ++ 11 (возможно, вы замените часть этого материала на функции NSString / C, но это менее подробное. Это дает вам два механизма: splitSystemVersion дает вам массив из всех частей, которые полезно, если вы просто хотите включить основную версию (например, switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }).

#include <boost/lexical_cast.hpp>

- (std::vector<int>) splitSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    std::vector<int> versions;
    auto i = version.begin();

    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        versions.push_back(boost::lexical_cast<int>(versionPart));
    }

    return versions;
}

/** Losslessly parse system version into a number
 * @return <0>: the version as a number,
 * @return <1>: how many numeric parts went into the composed number. e.g.
 * X.Y.Z = 3.  You need this to know how to compare again <0>
 */
- (std::tuple<int, int>) parseSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    return {versionAsNumber, nParts};
}


/** Assume that the system version will not go beyond X.Y.Z.W format.
 * @return The version string.
 */
- (int) parseSystemVersionAlt {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end() && nParts < 4) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    // don't forget to pad as systemVersion may have less parts (i.e. X.Y).
    for (; nParts < 4; nParts++) {
        versionAsNumber *= 100;
    }

    return versionAsNumber;
}
0
ответ дан Vitali 23 August 2018 в 02:43
поделиться
/*
 *  System Versioning Preprocessor Macros
 */ 

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

/*
 *  Usage
 */ 

if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {
    ...
}

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
    ...
}
1040
ответ дан yasirmturk 23 August 2018 в 02:43
поделиться
  • 1
    +1. Сохранение этого в заголовке, которое вы можете включить в случае необходимости, является самым простым решением, о котором я могу думать. В некоторых случаях это более надежно, чем проверка доступности с помощью NSClassFromString. Другой пример - в iAd, где, если вы используете ADBannerContentSizeIdentifierPortrait в версии до 4.2, вы получите EXEC_BAD_ACCESS, но эквивалент ADBannerContentSizeIdentifier320x50 устарел после 4.1. – Rab 12 December 2011 в 16:32
  • 2
    превосходен. Именно то, что мне нужно, чтобы заставить его работать. – Himanshu Singh 2 January 2012 в 13:51
  • 3
    Хорошие макросы, спасибо. Это должен быть правильный (лучший) ответ. – jjxtra 27 March 2012 в 17:24
  • 4
    – Paul de Lange 20 November 2012 в 15:11
  • 5
    Это не работает в течение 10 секунд. Например, сравнение 4.10 и 4.9 дало бы неправильный результат. – pzulw 11 July 2013 в 17:55
  • 6
    Нужно быть очень осторожным при использовании дополнительных .0 номеров. Например, SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0") дает неверный результат на iOS 7.0. – Yan 24 September 2013 в 16:00
  • 7

Я рекомендую:

if ([[[UIDevice currentDevice] systemVersion] floatValue] > 3.13) {
    ; // ...
}

credit: Как настроить таргетинг на определенную версию iPhone?

19
ответ дан Community 23 August 2018 в 02:43
поделиться
  • 1
    Хм, нет. Это неправильно в нескольких важных аспектах. 1: Номера версий не всегда являются простым числом с плавающей запятой, например "4.2.1" является допустимым номером версии iOS. 2: Вы выполняете сравнение с плавающей точкой. Из-за конечной точности чисел с плавающей запятой ваше сравнение может потерпеть неудачу (или преуспеть), если вы этого не ожидали. – Mac 2 July 2012 в 05:11
  • 2
    И самая проклятая причина, 3: Номера Float имеют различный порядок, чем строки: 4.10 < 4.2, но "4.10" > "4.2". – yakovlev 22 August 2012 в 21:02
  • 3
    еще больше осуждать? [@ & Quot; x.y.z & Quot; floatValue] возвращает x.y, поэтому 3.1.3 всегда будет возвращать 3.1, а не 3.13. – Vitali 30 November 2012 в 04:47
  • 4
    Строки могут иметь различный порядок, который плавает, но «4.10». & Lt; & Quot; 4,2 & Quot ;. – pzulw 11 July 2013 в 17:54
Другие вопросы по тегам:

Похожие вопросы: