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


848

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

[[UIDevice currentDevice].systemVersion floatValue]

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

if (version > 3.1.3) { }

Как мне этого добиться?


5
Примечание модератора : Со временем на этот вопрос набралось более 30 ответов. Перед добавлением нового ответа убедитесь, что ваше решение еще не было предоставлено.
Мэтт

3
Начиная Xcode 7, if #available(iOS 9, *) {}в Swift. Начиная Xcode 9, if (@available(iOS 11, *)) {}в цель-c.
Cœur

Ответы:


1002

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


По 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
}

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

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


161
Есть конкретные случаи, когда проверка версии системы оправдана. Например, пара классов и методов, которые были закрытыми в 3.x, были опубликованы в 4.0, поэтому, если вы просто проверите их доступность, вы получите неверный результат в 3.x. Кроме того, способ, которым UIScrollView обрабатывают шкалы масштабирования, слегка изменился в 3.2 и выше, поэтому вам необходимо проверить версии ОС, чтобы правильно обработать результаты.
Брэд Ларсон

2
iOS 3.2 не отображается для отправки -viewWillAppearв UISplitViewController. Мой взлом состоит в том, чтобы определить, является ли <iOS 4.0, и отправить его в контроллер подробного вида самостоятельно в Root View -didSelectRowAtIndexPath.
сентября

10
Вы должны быть немного осторожны здесь, потому что [@"10.0" compare:@"10" options:NSNumericSearch]возвращается NSOrderedDescending, что вполне может быть не предназначено вообще. (Я мог бы ожидать NSOrderedSame.) Это, по крайней мере, теоретическая возможность.
SK9

Да, я только что столкнулся со случаем, когда нужно было обойти ошибку iOS 5. respondsToSelectorи др. не справились бы с этой задачей - должны сравнивать версии.
Hot Licks

2
С появлением TVos это стало еще важнее. Посмотрите, как TVos вернет 9.0, пока используется 9.1 SDK. Поэтому лучше проверить класс или метод (селектор), после этого вам следует проверять NSFoundationVersionNumberи только, если это невозможно, если вы проверяете версии системы UIDevice.
rckoenes

1055
/*
 *  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.
Поль де Ланж,

7
Это не работает в течение 10 секунд. Например, сравнение 4.10 и 4.9 даст неверный результат.
pzulw

7
Нужно быть очень осторожным при использовании дополнительных .0номеров. Например SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")дает неверный результат на iOS 7.0.
Ян

1
Я только что проверил, поместил это в свой файл .pch, и он отлично работает (по крайней мере,
сборка

253

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

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}

40
+1 Это на самом деле самый безопасный и точный вариант здесь.
mxcl

8
Гм .. NSFoundationVersionNumber_iOS_6_1не существует в iOS 5 SDK.
Кюли,

2
@Kjuly, вы можете определить недостающие номера версий самостоятельно: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (взгляните на строку 102-130)
CarlJ

3
нет, вы не правы, 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

7
Нет, но Apple добавит NSFoundationVersionNumber_iOS_8_0в iOS 9. просто проверьте NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ

111

Начиная 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
}

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


Как это можно перевернуть в Objective-C или Swift?
Legoless

@Legolessif (...) {} else { ... }
Cœur

Могу ли я использовать guardв Objective-C вместо того, чтобы оставить блок открытым и отступ в elseоператоре?
Legoless

@Legoless нет, просто используйте пустой ifблок с последующим else.
Cœur

1
Это решение, которое у меня сейчас есть, просто хотел избежать ненужных отступов и пустых ifблоков.
Legoless

45

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

37

Пытаться:

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
Это может сделать логику менее ясной. Однако операция должна быть эквивалентной.
Джонатан Гринспан

1
Сравнение между двумя целыми числами, безусловно, не очень дорого.
KPM

Это действительно вопрос стиля. Затраты на отправку сообщений значительно перевесят дополнительное целочисленное сравнение.
Джонатан Гринспан

35

Предпочитаемый подход

В 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.NumericSearchon 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 .


9

Я всегда храню их в своем файле 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)

Отлично. Лучше поместить это в .pchфайл вашего проекта XCode
Vaibhav Jhaveri

1
Я помещаю все свои константы в мой Constants.hфайл, который импортируется в мой pchфайл.
Сегев

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;
  }


}

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

6

С классом Version, который содержится в проекте 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-версия
ТакахикоКавасаки / nv-ios-версия

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


5

Новый способ проверки версии системы с использованием быстрых Forget [[UIDevice currentDevice] systemVersion] и NSFoundationVersionNumber.

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

     import Foundation

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

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

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

4
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

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


4

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

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

[[UIDevice currentDevice] systemVersion]

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

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

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



3

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

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

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

ч / т этот ответ


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
}       

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
 }

просто удаление десятичных знаков - неправильный подход. рассмотрим компонент длиной более 1 символа, например 6.1.10. тогда этот алгоритм даст 6110 > 700, что не правильно.
ardnew

Я понимаю, что Apple плохо выкатывает новые версии, но в большинстве случаев второе число версий никогда не выходило за пределы 5, поэтому 10 не обсуждается. Это временный подход, поэтому, если он обрабатывает регистр для 2 компонентов, вы можете изменить его для обработки четырех вариантов регистра, если вы хотите сделать это вручную. Как бы то ни было, этот подход был прокомментирован во времена iOS6 или 7. У iOS 9 и 10 есть намного лучшие способы его проверки, например #available.
NaXir

2

Попробуйте следующий код:

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


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 файл:

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

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

Решение для проверки версии 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")
}

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


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


0

Более общая версия в 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
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

float versionToBeCompared = 3.1.3;не могу даже скомпилировать.
Пан

0

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

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

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

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
}

Я думаю, что версия должна быть 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) }
Кастор
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.