1. 程式人生 > >iOS版本

iOS版本

你會 方便 mage ati 存儲 註意 之前 fan 一個

1.靜態檢查

靜態檢查,即在編譯時段就檢查當前SDK編譯與構建應用是否能使用某個API或已經不支持某個API。

編譯常量

__IPHONE_OS_VERSION_MIN_REQUIRED

用來判斷是否當前SDK版本“仍然”支持或具有某些功能。

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000
    //minimum deployment target is 8.0, so it’s safe to use iOS 8-only code
    當前SDK最小支持的設備系統,即8.0,所以在iOS 8.0設備上是安全的

#else
    //you can use iOS8 APIs, but the code will need to be backwards
    //compatible or it will crash when run on an iOS 7 device
    你仍然可以使用iOS 8的API,但是在iOS 7的設備上可能會crash.
#endif

__IPHONE_OS_VERSION_MAX_ALLOWED

用來判斷是否當前版本“開始”支持或具有某些功能;

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
    //you can use iOS 10 APIs here because the SDK supports them
    //but the code may still crash if run on an iOS 8 device
    可以使用最新的iOS 10的API,開始支持的新功能。但是仍然可能會在iOS 8的設備上crash。
#else
    //this code can’t use iOS 10 APIs as the SDK version doesn’t support them
    不能使用iOS 10的API,只能使用iOS 10之前的。
#endif

針對Xcode的舊版本,或者設備上的就版本,不存在相應的宏,采用如下定義:

#ifndef __IPHONE_10_0
#define __IPHONE_10_0 100000
#endif
 
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
 
#else
 
#endif

2.動態檢查

CoreFoudation/NSFoundation版本宏

類似於iOS 系統版本宏,系統還給出了CoreFoudation和NSFoudation宏,並且給出了kCFCoreFoundationVersionNumber和NSFoundationVersionNumber兩個值。這兩個值均是double值。

在iOS10.2.1系統上,以上兩個值,分別是:1348.220000、1349.130000。
在Debug下,兩個值的存儲po出來分別是:1348.22、1349.1300000000001。

kCFCoreFoundationVersionNumber

詳見 CoreFoundatin/CFBase.h中定義。

NSFoundationVersionNumber

詳見 Foundation/NSObjRuntime.h中定義。

針對上面的宏,寫起來復雜,所以可以定義一個宏,來簡化書寫:

#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_10_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_10_0 1299
#endif

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
#define IF_IOS10_OR_GREATER(...) if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_10_0) { __VA_ARGS__ }
#else
#define IF_IOS10_OR_GREATER(...)
#endif

#define IF_PRE_IOS10(...) if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_10_0) { __VA_ARGS__ }

IF_IOS10_OR_GREATERIF_PRE_IOS10就可以在使用中快捷調用。

IF_IOS10_OR_GREATER
(
    //iOS 10 code here
);

然而,即使上面這種方法可以簡單的檢查系統版本,你仍然無法保證絕對正確,因為你會發現以上宏中不同的系統版本中存在相同的值。

缺陷:當你要判斷那些剛好存在相同值的版本的時候,也是一個危險的判斷。

3.檢查運行的iOS 系統版本

if ([[ [UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
}

註意:上面的判斷方法,在判斷整數版本的時候,使用起來挺方便,也不會出什麽大問題。但是仍然是極其危險的。因為float在計算機中的存儲,是近似而非精確。

比如,最新的iOS 10.2.1系統,有以下一段代碼:

NSString *version = [[UIDevice currentDevice] systemVersion];
int int_ver = [version intValue];
float float_ver = [version floatValue];
NSLog(@"%@-%d-%f",version,int_ver,float_ver);


打印出來如下的結果:

10.2.1-10-10.200000

可以看出,10.2.1打印出來的floatValue值,是【10.20000】,這還算小事。更為致命的是,在控制臺調試時發現:

技術分享

所以,假如比較10.2.1和10.2.2比較,就很難得出結果。

鑒於此,以上方法不推薦使用!最好不用!

那麽,什麽是好的運行時判斷系統的方法呢?

定義判斷版本的宏:

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

但是,由於NSString的compare方法本身的缺陷:

NSInteger compareResult = [@"10.0" compare:@"10" options:NSNumericSearch];


遺憾的是,上面的系統版本判斷也是有漏洞的。但是相對於之前的漏洞,這個漏洞似乎可以接受。
上面返回的結果:NSOrderedDescending,即10.0相比於10是低版本。

4.iOS 8之後,NSOperatingSystemVersion

NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];

NSProcessInfo還提供了:

NSOperatingSystemVersion v = (NSOperatingSystemVersion){8,1,3};
if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:v]) {
 
}

以上這個方法,只有在iOS 8之後,但是對於一些超級APP,仍然在支持iOS 7,所以也就無能為力了。

 轉自

iOS版本