计划一

double systemVersion = [UIDevice currentDevice].systemVersion.boolValue;
if (systemVersion >= 7.0) {
    // >= iOS 7.0
} else {
    // < iOS 7.0
}
if (systemVersion >= 10.0) {
    // >= iOS 10.0
} else {
    // < iOS 10.0
}

假如仅仅大致判别是哪个体系版别,上面的办法是可行的,假如详细到某个版别,如 10.0.1,那就会有偏差。咱们知道 systemVersion 依旧是10.0。

计划二

NSString *systemVersion = [UIDevice currentDevice].systemVersion;
NSComparisonResult comparisonResult = [systemVersion compare:@"10.0.1" options:NSNumericSearch];
if (comparisonResult == NSOrderedAscending) {
    // < iOS 10.0.1
} else if (comparisonResult == NSOrderedSame) {
    // = iOS 10.0.1
} else if (comparisonResult == NSOrderedDescending) {
    // > iOS 10.0.1
}
// 或者
if (comparisonResult != NSOrderedAscending) {
    // >= iOS 10.0.1
} else {
    // < iOS 10.0.1
}

有篇博客说到这种办法不靠谱。比方体系版别是 10.1.1,而咱们供给的版别是 8.2,会返回NSOrderedAscending,即认为 10.1.1 < 8.2 。

其实,用这样的比较方式 NSComparisonResult comparisonResult = [systemVersion compare:@"10.0.1"],确实会呈现这种状况,因为默认是每个字符逐一比较,即 1(0.1.1) < 8(.2),成果可想而知。但我是用 NSNumericSearch 方式比较的,即数值的比较,不是字符比较,也不需要转化成NSValue(NSNumber) 再去比较。

计划三

if (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0) {
    // >= iOS 7.0
} else {
    // < iOS 7.0
}
// 或者
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) {
    // >= iOS 7.0
} else {
    // < iOS 7.0
}

这些宏界说是 Apple 预先界说好的,如下:

#if TARGET_OS_IPHONE
...
#define NSFoundationVersionNumber_iOS_9_4 1280.25
#define NSFoundationVersionNumber_iOS_9_x_Max 1299
#endif

细心的童靴或许已经发现问题了。Apple 没有供给 iOS 10 今后的宏?,咱们要判别iOS10.0今后的版别该怎么做呢?
有篇博客中说到,iOS10.0今后版别号供给了,而且逐次降低了,并供给了根据。

#if TARGET_OS_MAC
#define NSFoundationVersionNumber10_1_1	425.00
#define NSFoundationVersionNumber10_1_2	425.00
#define NSFoundationVersionNumber10_1_3	425.00
#define NSFoundationVersionNumber10_1_4	425.00
...
#endif

我想这位童鞋或许没仔细看, 这两组宏是别离针对iPhone和macOS的,不能混为一谈的。

所以也只能像下面的方式来大致判别iOS 10.0, 但之前的iOS版别是能够精确判别的。

if (NSFoundationVersionNumber > floor(NSFoundationVersionNumber_iOS_9_x_Max)) {
    // > iOS 10.0
} else {
    // <= iOS 10.0
}

计划四

在iOS8.0中,Apple也供给了NSProcessInfo 这个类来检测版别问题。

@property (readonly) NSOperatingSystemVersion operatingSystemVersion NS_AVAILABLE(10_10, 8_0);
- (BOOL) isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version NS_AVAILABLE(10_10, 8_0);

所以这样检测:

if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 8, .minorVersion = 3, .patchVersion = 0}]) {
     // >= iOS 8.3
} else {
     // < iOS 8.3
}

用来判别iOS 10.0以上的各个版别也是没有问题的,唯一的缺点就是不能精确版别是哪个版别,当然这种状况很少。假如是这种状况,能够经过字符串的比较判别。

计划五

经过判别某种特定的类有没有被界说,或者类能不能呼应哪个特定版别才有的办法。
比方,UIAlertController 是在iOS 8.0才被引进来的一个类,咱们这个根据来判别版别

if (NSClassFromString(@"UIAlertController")) {
    // >= iOS 8.0
} else {
    // < iOS 8.0
}

说到这儿,就趁便提一下在编译期间如何进行版别控制,依然用UIAlertController 来阐明。

NS_CLASS_AVAILABLE_IOS(8_0) @interface UIAlertController : UIViewController

NS_CLASS_AVAILABLE_IOS(8_0) 这个宏阐明,UIAlertController 是在iOS8.0才被引进来的API,那假如咱们在iOS7.0上运用,应用程序就会挂掉,那么如何在iOS8.0及今后的版别运用UIAlertController ,而在iOS8.0以前的版别中依然运用UIAlertView 呢?

这儿咱们会介绍一下在#import <AvailabilityInternal.h> 中的两个宏界说:

*__IPHONE_OS_VERSION_MIN_REQUIRED

*__IPHONE_OS_VERSION_MAX_ALLOWED

从字面意思就能够直到,__IPHONE_OS_VERSION_MIN_REQUIRED 表明iPhone支撑最低的版别体系,__IPHONE_OS_VERSION_MAX_ALLOWED 表明iPhone答应最高的体系版别。

__IPHONE_OS_VERSION_MAX_ALLOWED 的取值来自iOS SDK的版别,比方我现在运用的是Xcode Version 8.2.1(8C1002),SDK版别是iOS 10.2,怎么看Xcode里SDK的iOS版别呢?

进入PROJECT,挑选Build Setting,在Architectures中的Base SDK中能够查看当时的iOS SDK版别。

打印这个宏,能够看到它一向输出100200。

__IPHONE_OS_VERSION_MIN_REQUIRED 的取值来自项目TARGETS的Deployment Target,即APP乐意支撑的最低版别。假如咱们修正它为8.2,打印这个宏,会发现输出80200,默认为10.2。

一般,__IPHONE_OS_VERSION_MAX_ALLOWED 能够代表当时的SDK的版别,用来判别当时版别是否开始支撑或具有某些功用。而__IPHONE_OS_VERSION_MIN_REQUIRED 则是当时SDK支撑的最低版别,用来判别当时版别是否依然支撑或具有某些功用。

回到UIAlertController 运用的问题,咱们就能够运用这些宏,增加版别检测判别,从而使咱们的代码更健壮。

 - (void)showAlertView {
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Title" message:@"message" delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
    [alertView show];
#else
    if (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_8_0) {
        UIAlertController *alertViewController = [UIAlertController alertControllerWithTitle:@"Title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
        UIAlertAction *otherAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
        [alertViewController addAction:cancelAction];
        [alertViewController addAction:otherAction];
        [self presentViewController:alertViewController animated:YES completion:NULL];
    }
#endif
}

计划六

iOS 11.0 今后,Apple加入了新的API,今后咱们就能够像在Swift中的那样,很方便的判别体系版别了。

if (@available(iOS 11.0, *)) {
	// iOS 11.0 及今后的版别
} else {
	// iOS 11.0 之前
}

参考链接

  • www.360doc.com/content/14/…
  • www.tuicool.com/articles/3I…
  • segmentfault.com/a/119000000…
  • www.tuicool.com/articles/Nr…