Як перевірити версію 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, *)) {}в Objective-c.
Cœur

Відповіді:


1001

Швидка відповідь ...


За 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. Передача нуля в цей 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
Існують конкретні випадки, коли перевірка версії системи є виправданою. Наприклад, кілька класів і методів, які були приватними n 3.x, були оприлюднені в 4.0, тож якщо ви просто перевірили їх наявність, ви отримаєте неправильний результат у 3.x. Крім того, спосіб, яким UIScrollViews обробляє масштаби масштабування, суттєво змінився в 3.2 і вище, тож вам слід перевірити версії ОС, щоб правильно обробити результати.
Бред Ларсон

2
Здається, iOS 3.2 не надсилає -viewWillAppearа UISplitViewController. Мій хак полягає в тому, щоб визначити, чи <iOS 4.0, і надіслати його самому Контролеру детального перегляду в Корінний вид -didSelectRowAtIndexPath.
jww

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

Так, я щойно стикався з випадком, коли помилку з iOS 5 потрібно було обійти. respondsToSelectorта ін. не зробили б справи - доведеться порівнювати версії.
Гарячі лизання

2
З впровадженням 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, де, якщо ви використовуєте ADBannerContentSizeIdentifierPor Portrait у версії до 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 файл, і він чудово працює (будуючи Xcode 5 принаймні)
whyoz

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

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

Для версії можна вказати ГОЛОВНУ, МІНОРУ або ПАТЧ (див. 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?
Безголосий

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

Чи можна використовувати guardв Objective-C замість того, щоб залишати блок відкритим і відступ у elseвиписці?
Legoless

@Legoless ні, просто використовуйте порожній ifблок, за яким слід an 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
}

Швидка версія:

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 options: NSNumericSearch] == NSOrderedDescending); // версія ОС> = 3.1.3 else; // версія ОС <3.1.3`
Роб

3
Це може зробити логіку менш зрозумілою. Однак операція повинна бути рівнозначною.
Джонатан Гринспан

1
Порівняння двох цілих чисел, безумовно, не дуже дороге.
КПМ

Це справді питання стилю. Накладні витрати на відправлення повідомлень значно перевищують додаткове ціле порівняння.
Джонатан Грінспан

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

Для мінімальних цілей розгортання в прошивкою 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 .


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

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-версії проекту (Ліцензія 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-версія

Блог: Отримайте та порівняйте версію iOS під час виконання з класом Version
Отримайте та порівняйте версію iOS під час виконання з класом Version


5

Новий спосіб перевірити версію системи за допомогою swift Забудьте [[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
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

if (_kisiOS7) {
            NSLog(@"iOS7 or greater")
} 
else {
           NSLog(@"Less than iOS7");
}

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 не викликає сумнівів. Це підхід adhoc, тому якщо він обробляє корпус для двох компонентів, ви можете змінити його для обробки чотирьох макетів, якщо ви хочете зробити це вручну. Так чи інакше цей підхід був прокоментований під час iOS6 або 7. У iOS 9 і 10 є набагато кращі способи перевірити його, тобто #available.
NaXir

2

Спробуйте наведений нижче код:

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


1

Як варіант розчину ясимтурка, я визначив одну функцію та кілька значень перерахунків замість п'яти макросів. Я вважаю це більш елегантним, але це питання смаку.

Використання:

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.