Как проверить версию iOS?

756

Я хочу проверить, больше ли версия iOS устройства больше 3.1.3 Я пробовал такие вещи, как:

[[UIDevice currentDevice].systemVersion floatValue]

но он не работает, я просто хочу:

if (version > 3.1.3) { }

Как я могу это достичь?

  • 4
    Примечание модератора : Со временем на этот вопрос набралось более 30 ответов. Перед добавлением нового ответа убедитесь, что ваше решение еще не было предоставлено.
  • 0
    Запуск Xcode 7, if #available(iOS 9, *) {} в Swift. Запуск Xcode 9, if (@available(iOS 11, *)) {} в if (@available(iOS 11, *)) {} -c.
Показать ещё 1 комментарий
Теги:

40 ответов

883
Лучший ответ

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


С 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).

  • 160
    Есть конкретные случаи, когда проверка версии системы оправдана. Например, пара классов и методов, которые были закрытыми в 3.x, были опубликованы в 4.0, поэтому, если вы просто проверите их доступность, вы получите неверный результат в 3.x. Кроме того, способ, которым UIScrollView обрабатывают шкалы масштабирования, слегка изменился в 3.2 и выше, поэтому вам необходимо проверить версии ОС, чтобы правильно обработать результаты.
  • 2
    iOS 3.2 не отправляет -viewWillAppear в UISplitViewController . Мой взлом состоит в том, чтобы определить, является ли <iOS 4.0, и отправить его самому контроллеру подробного представления в -didSelectRowAtIndexPath .
Показать ещё 9 комментариев
989
/*
 *  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")) {
    ...
}
  • 20
    +1. Хранить это в заголовке, который вы можете включить в случае необходимости, - самое простое решение, которое я могу придумать. В некоторых случаях это более надежно, чем проверка доступности с помощью NSClassFromString. Другой пример - в iAd, где, если вы используете ADBannerContentSizeIdentifierPortrait в версии до 4.2, вы получите EXEC_BAD_ACCESS, но эквивалентный ADBannerContentSizeIdentifier320x50 считается устаревшим после 4.1.
  • 1
    Другое место, где я использую это, с UIPageViewController и установкой стиля в UIPageViewControllerTransitionStyleScroll в iOS6.
Показать ещё 6 комментариев
246

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

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}
  • 39
    +1 Это на самом деле самый безопасный и точный вариант здесь.
  • 8
    Гм ... NSFoundationVersionNumber_iOS_6_1 не существует в iOS 5 SDK.
Показать ещё 16 комментариев
69

Запуск 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
}

documentation

  • 0
    Как это можно перевернуть в Objective-C или Swift?
  • 0
    @Legoless if (...) {} else { ... }
Показать ещё 6 комментариев
36

Try:

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
}
  • 2
    Почему бы не изменить порядок здесь и сохранить сравнение, поскольку @ "3.1.3" и systemVersion являются NSStrings? Т.е.: `if ([@" 3.1.3 "сравнить: [UIDevice currentDevice]. Опции systemVersion: NSNumericSearch] == NSOrderedDescending); // версия ОС> = 3.1.3 else; // версия ОС <3.1.3`
  • 3
    Это может сделать логику менее ясной. Однако операция должна быть эквивалентной.
Показать ещё 2 комментария
35

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

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

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

Это предпочтительнее проверки respondsToSelector и т.д. (What New in 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.

35

Это используется для проверки совместимости версии 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 версия:

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
}

Текущие версии Swift должны использовать это:

if #available(iOS 12, *) {
    //iOS 12 specific code here
} else {
    //older than iOS 12 code here
}
18

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

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

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

  • 24
    Нет Это неправильно в нескольких важных аспектах. 1: Номера версий не всегда являются простыми числами с плавающей точкой, например, «4.2.1» - это действительный номер версии iOS. 2: Вы делаете сырое сравнение с плавающей запятой. Из-за конечной точности чисел с плавающей запятой, ваше сравнение может потерпеть неудачу (или удастся), если вы иначе не ожидаете этого.
  • 29
    И самая ужасная причина, 3: числа с плавающей точкой имеют другой порядок, чем строки: 4.10 < 4.2 , но "4.10" > "4.2" .
Показать ещё 2 комментария
8

Я всегда сохраняю их в файле 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)
  • 0
    Отлично. Лучше поместить это в .pch файл вашего проекта XCode
  • 1
    Я помещаю все свои константы в мой файл Constants.h который импортируется в мой файл pch .
6

С классом Версия, который содержится в nv-ios-version проекте (Apache License, версия 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-version
TakahikoKawasaki/nv-ios-version

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

6
+(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;
  }


}
  • 0
    это работает хорошо, игнорирует все десятичные точки ..
  • 0
    @Jef Периоды не являются десятичными точками в версиях и актуальны. Ваш ответ не игнорирует периоды, Он потерпит неудачу, если это так. В версиях каждого элемента, разделенного точками, указан полный номер. Пример: «1.23.45» больше, чем «1.2.345», поскольку второй элемент «23» больше, чем «2». Если бы вы исключили периоды, это было бы то же число.
5

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

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

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

     import Foundation

     let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
     NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
4

Тестирование по меньшей мере для iOS 10 в Swift 3:

if (ProcessInfo.processInfo.isOperatingSystemAtLeast(OperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0))) {

}
4

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

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

[[UIDevice currentDevice] systemVersion]

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

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

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

  • 0
    Я думаю, что это хорошее решение для многих случаев
4
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

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

4

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

Если это не вариант, вам нужно быть немного осторожным, потому что [@"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
3
#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
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

if (_kisiOS7) {
            NSLog(@"iOS7 or greater")
} 
else {
           NSLog(@"Less than iOS7");
}
  • 1
    спасибо ... он работает
2
NSString *deviceVersion = [[UIDevice currentDevice] systemVersion];
2

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

[[UIDevice currentDevice] systemVersion]
2

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

NSString *versionString = [[UIDevice currentDevice] systemVersion];
2

Есть версия вроде 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
 }
  • 0
    просто удаление десятичных знаков - неправильный подход. рассмотрим компонент длиной более 1 символа, например 6.1.10 . тогда этот алгоритм даст 6110 > 700 , что не правильно.
  • 0
    Я понимаю, что Apple плохо выкатывает новые версии, но в большинстве случаев второе число версий никогда не выходило за пределы 5, поэтому 10 не обсуждается. Это временный подход, поэтому, если он обрабатывает регистр для 2 компонентов, вы можете изменить его для обработки четырех вариантов регистра, если вы хотите сделать это вручную. Как бы то ни было, этот подход был прокомментирован во времена iOS6 или 7. У iOS 9 и 10 есть намного лучшие способы его проверки, например #available.
1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
1

Решение для проверки версии 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, вы, к сожалению, заметите, что никогда не пройдете через оставшуюся часть фрагмент кода.

  • 0
    Почему отказано в голосовании? Это решение отлично работает с использованием Swift и любой версии iOS. Особенно проверка существования класса просто идеальна.
1

Используя рекомендуемый способ... если в файлах заголовков нет определения, вы всегда можете распечатать его на консоли с помощью устройства желаемой версии 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

Я знаю, что это старый вопрос, но кто-то должен был упомянуть макросы времени компиляции в 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 этот ответ

1

Как вариант решения yasimturks, я определил одну функцию и несколько значений enum вместо пяти макросов. Я нахожу его более элегантным, но это вопрос вкуса.

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

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

.h файл:

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

BOOL systemVersion(Comparison test, NSString* version);

.m file:

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.

0

Добавьте приведенный ниже код Swift в свой проект и легко получайте доступ к такой информации, как версия iOS и устройство.

class DeviceInfo: NSObject {

    struct ScreenSize
    {
        static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
        static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
        static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
        static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
    }

    struct DeviceType
    {
        static let IS_IPHONE_4_OR_LESS =  UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
        static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
        static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH >= 667.0
        static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
        static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
        static let IS_IPAD      = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
        static let IS_IPAD_PRO  = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0
    }

    struct VersionType{
        static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValue
        static let iOS7 = (VersionType.SYS_VERSION_FLOAT < 8.0 && VersionType.SYS_VERSION_FLOAT >= 7.0)
        static let iOS8 = (VersionType.SYS_VERSION_FLOAT >= 8.0 && VersionType.SYS_VERSION_FLOAT < 9.0)
        static let iOS9 = (VersionType.SYS_VERSION_FLOAT >= 9.0 && VersionType.SYS_VERSION_FLOAT < 10.0)
        static let iOS10 = (VersionType.SYS_VERSION_FLOAT >= 9.0 && VersionType.SYS_VERSION_FLOAT < 11.0)
    }
}
0

Здесь вы можете получить всю информацию, связанную с устройством, здесь https://github.com/aleemrazzaq/ARCompactDeviceInfo

0

Вот быстрая версия макросов yasirmturk. Надеюсь, что это поможет некоторым народам.

// MARK: System versionning

func SYSTEM_VERSION_EQUAL_TO(v: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
}

func SYSTEM_VERSION_GREATER_THAN(v: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN(v: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
}

let kIsIOS7: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("7")
let kIsIOS7_1: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("7.1")
let kIsIOS8: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("8")
let kIsIOS9: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("9")
0

Вот быстрая версия:

struct iOSVersion {
    static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue
    static let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)
    static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)
    static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
}

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

if iOSVersion.iOS8 {
    //Do iOS8 code here
}
  • 0
    Я думаю, что Версия должна быть iOSVersion в строке 3-6, например struct iOSVersion { static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue static let iOS7 = (iOSVersion.SYS_VERSION_FLOAT < 8.0 && iOSVersion.SYS_VERSION_FLOAT >= 7.0) static let iOS8 = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0) static let iOS9 = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0) }
0

Пример 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
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
    float versionToBeCompared = 3.1.3; не могу даже скомпилировать.
0

Попробуйте это

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { 
// do some work
}
  • 0
    Объясните, что это делает.
  • 0
    if проверит, является ли версия os ios 7 или нет
0

Более общая версия в Obj-С++ 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;
}
-1

Мое решение - добавить утилитный метод в ваш класс утилит (подсказка подсказки), чтобы проанализировать версию системы и вручную компенсировать упорядочение числа с плавающей запятой.

Кроме того, этот код довольно прост, поэтому я надеюсь, что он поможет некоторым новичкам. Просто перейдите в целевой поплавок и верните BOOL.

Объявите его в своем общем классе следующим образом:

(+) (BOOL) iOSMeetsOrExceedsVersion:(float)targetVersion;

Назовите его следующим образом:

BOOL shouldBranch = [SharedClass iOSMeetsOrExceedsVersion:5.0101];

(+) (BOOL) iOSMeetsOrExceedsVersion:(float)targetVersion {

/*
 Note: the incoming targetVersion should use 2 digits for each subVersion --

 example 5.01 for v5.1, 5.11 for v5.11 (aka subversions above 9), 5.0101 for v5.1.1, etc.
*/

// Logic: as a string, system version may have more than 2 segments (example: 5.1.1)
// so, a direct conversion to a float may return an invalid number
// instead, parse each part directly

NSArray *sysVersion = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
float floatVersion = [[sysVersion objectAtIndex:0] floatValue];
if (sysVersion.count > 1) {
    NSString* subVersion = [sysVersion objectAtIndex:1];
    if (subVersion.length == 1)
        floatVersion += ([[sysVersion objectAtIndex:1] floatValue] *0.01);
    else
        floatVersion += ([[sysVersion objectAtIndex:1] floatValue] *0.10);
}
if (sysVersion.count > 2) {
    NSString* subVersion = [sysVersion objectAtIndex:2];
    if (subVersion.length == 1)
        floatVersion += ([[sysVersion objectAtIndex:2] floatValue] *0.0001);
    else
        floatVersion += ([[sysVersion objectAtIndex:2] floatValue] *0.0010);
}

if (floatVersion  >= targetVersion) 
    return TRUE;

// else
return FALSE;
 }
-2

Есть несколько проблем с двумя популярными ответами:

  • Сравнение строк с использованием NSNumericSearch иногда имеет неинтуитивные результаты (макросы SYSTEM_VERSION_* все страдают от этого):

    [@"10.0" compare:@"10" options:NSNumericSearch] // returns NSOrderedDescending instead of NSOrderedSame
    

    FIX. Сначала сначала выполните нормализацию строк, а затем выполните сравнения. может раздражать, пытаясь получить обе строки в одинаковых форматах.

  • Использование символов версии фреймворка рамки невозможно при проверке будущих выпусков

    NSFoundationVersionNumber_iOS_6_1 // does not exist in iOS 5 SDK
    

    FIX. Выполните два отдельных теста, чтобы убедиться, что символ существует, И ТОГДА сравните символы. Однако здесь другое:

  • Символы версий фреймовых фреймов не уникальны для версий iOS. Несколько версий iOS могут иметь одну и ту же версию фреймворка.

    9.2 & 9.3 are both 1242.12
    8.3 & 8.4 are both 1144.17
    

    FIX. Я считаю, что эта проблема неразрешима.


Чтобы устранить эти проблемы, следующий метод обрабатывает строки номера версии в качестве номеров base-10000 (каждый компонент major/minor/patch - это отдельная цифра) и выполняет базовое преобразование в десятичное для простого сравнения с использованием целых операторов.

Были добавлены два других метода для удобного сравнения строк версии iOS и сравнения строк с произвольным количеством компонентов.

+ (SInt64)integerFromVersionString:(NSString *)versionString withComponentCount:(NSUInteger)componentCount
{
    //
    // performs base conversion from a version string to a decimal value. the version string is interpreted as
    // a base-10000 number, where each component is an individual digit. this makes it simple to use integer
    // operations for comparing versions. for example (with componentCount = 4):
    //
    //   version "5.9.22.1" = 5*1000^3 + 9*1000^2 + 22*1000^1 + 1*1000^0 = 5000900220001
    //    and
    //   version "6.0.0.0" = 6*1000^3 + 0*1000^2 + 0*1000^1 + 0*1000^1 = 6000000000000
    //    and
    //   version "6" = 6*1000^3 + 0*1000^2 + 0*1000^1 + 0*1000^1 = 6000000000000
    //
    // then the integer comparisons hold true as you would expect:
    //
    //   "5.9.22.1" < "6.0.0.0" // true
    //   "6.0.0.0" == "6"       // true
    //

    static NSCharacterSet *nonDecimalDigitCharacter;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,
        ^{  // don't allocate this charset every time the function is called
            nonDecimalDigitCharacter = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
        });

    SInt64 base    = 10000; // each component in the version string must be less than base
    SInt64 result  =     0;
    SInt64 power   =     0;

    // construct the decimal value left-to-right from the version string
    for (NSString *component in [versionString componentsSeparatedByString:@"."])
    {
        if (NSNotFound != [component rangeOfCharacterFromSet:nonDecimalDigitCharacter].location)
        {
            // one of the version components is not an integer, so bail out
            result = -1;
            break;
        }
        result += [component longLongValue] * (long long)pow((double)base, (double)(componentCount - ++power));
    }

    return result;
}

+ (SInt64)integerFromVersionString:(NSString *)versionString
{
    return [[self class] integerFromVersionString:versionString
                               withComponentCount:[[versionString componentsSeparatedByString:@"."] count]];
}

+ (SInt64)integerFromiOSVersionString:(NSString *)versionString
{
    // iOS uses 3-component version string
    return [[self class] integerFromVersionString:versionString
                               withComponentCount:3];
}

Это несколько перспективное доказательство того, что оно поддерживает многие идентификаторы ревизий (через 4 цифры, 0-9999, изменение base для настройки этого диапазона) и может поддерживать произвольное количество компонентов (Apple, похоже, использует 3 компонента на данный момент, например major.minor.patch), но это можно явно указать с помощью аргумента componentCount. Убедитесь, что ваши componentCount и base не вызывают переполнение, т.е. Обеспечивают 2^63 >= base^componentCount!

Пример использования:

NSString *currentVersion = [[UIDevice currentDevice] systemVersion];
if ([Util integerFromiOSVersionString:currentVersion] >= [Util integerFromiOSVersionString:@"42"])
{
    NSLog(@"we are in some horrible distant future where iOS still exists");
}
-3

Все ответы выглядят немного большими. Я просто использую:

if (SYSTEM_VERSION_GREATER_THAN(@"7.0")){(..CODE...)}
if (SYSTEM_VERSION_EQUAL_TO(@"7.0")){(..CODE...)}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")){(..CODE...)}
if (SYSTEM_VERSION_LESS_THAN(@"7.0")){(..CODE...)}
if (SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(@"7.0")){(..CODE...)}

Конечно, замените @"7.0" на требуемую версию ОС.

  • 0
    Это ничего не отвечает.
  • 0
    @AndresCanella Полагаю, ответ будет, if (SYSTEM_VERSION_GREATER_THAN(@"7.0")){(..CODE...)} , так что это действительно отвечает на вопрос, нет?
Показать ещё 1 комментарий
-4
  • На главном экране нажмите Настройки > Общие > О.
  • Версия программного обеспечения вашего устройства должна появиться на этом экране.
  • Проверьте, больше ли номер версии, чем 3.1.3.
  • 0
    Могут ли люди, которые проголосовали за мой ответ, также объяснить, почему они это сделали? Это было бы полезно.
  • 0
    Вас опускают, потому что ваш ответ не подходит для этого сайта. Вопрос был в том, как проверить версию устройства с помощью кода, а не в пошаговой инструкции о том, как проверить настройки устройства. Ваш ответ будет более подходящим для Ask Different.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню