由于系统平台和SDK更新迭代,一部分过时的成员、方法会被彻底从SDK中移除,为了兼容旧的设备,这时就需要区分系统平台版本调用正确的API。
另一种情况是iOS设备的屏幕和设备参数不同,虽然UI上的AutoLayout技术能很好的解决显示适配问题,但仍有时候不得不根据平台版本进行编码。
有很多方法来区分平台版本,常用的有 [UIDevice currentDevice].systemVersion floatValue] ,或者根据SDK更新增加和淘汰的Class进行判断(不直观且必须对历史版本非常了解),根据设备情况判断(最不可取),通过NSObjCRuntime.h的宏定义判断(使用NSFoundationVersionNumber)。
最建议这种方法,因为可读性较高,支持iOS2以后的所有及可预见的未来版本。
举个例子:CFURLCreateStringByReplacingPercentEscapesUsingEncoding在iOS9中被完全移除,为了同时兼容iOS6版本,decodedUrlString代码如下:
1 #ifndef NSFoundationVersionNumber_iOS_7_0 2 #define NSFoundationVersionNumber_iOS_7_0 1047.20 3 #endif 4 5 -(NSString *)decodedUrlString:(NSString *)urlString { 6 if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_7_0) { 7 #pragma clang diagnostic push 8 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 9 NSString * decodedString = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (__bridge CFStringRef)urlString, CFSTR(""), kCFStringEncodingUTF8); 10 #pragma clang diagnostic pop 11 return decodedString; 12 } else { 13 return [urlString stringByRemovingPercentEncoding]; 14 } 15 }
解释:因为iOS8之前的SDK未定义NSFoundationVersionNumber_iOS_7_0,而iOS7之后可以使用stringByRemovingPercentEncoding方法代替前面的方法,这里给没有定义NSFoundationVersionNumber_iOS_7_0的情况手动定义它,使编译器能编译旧版本SDK。它的值见NSObjCRuntime.h中的定义,可用版本见开发文档:
FOUNDATION_EXPORT double NSFoundationVersionNumber; #if TARGET_OS_MAC #define NSFoundationVersionNumber10_0 397.40 #define NSFoundationVersionNumber10_1 425.00 #define NSFoundationVersionNumber10_1_1 425.00 #define NSFoundationVersionNumber10_1_2 425.00 #define NSFoundationVersionNumber10_1_3 425.00 #define NSFoundationVersionNumber10_1_4 425.00 #define NSFoundationVersionNumber10_2 462.00 #define NSFoundationVersionNumber10_2_1 462.00 #define NSFoundationVersionNumber10_2_2 462.00 #define NSFoundationVersionNumber10_2_3 462.00 #define NSFoundationVersionNumber10_2_4 462.00 #define NSFoundationVersionNumber10_2_5 462.00 #define NSFoundationVersionNumber10_2_6 462.00 #define NSFoundationVersionNumber10_2_7 462.70 #define NSFoundationVersionNumber10_2_8 462.70 #define NSFoundationVersionNumber10_3 500.00 #define NSFoundationVersionNumber10_3_1 500.00 #define NSFoundationVersionNumber10_3_2 500.30 #define NSFoundationVersionNumber10_3_3 500.54 #define NSFoundationVersionNumber10_3_4 500.56 #define NSFoundationVersionNumber10_3_5 500.56 #define NSFoundationVersionNumber10_3_6 500.56 #define NSFoundationVersionNumber10_3_7 500.56 #define NSFoundationVersionNumber10_3_8 500.56 #define NSFoundationVersionNumber10_3_9 500.58 #define NSFoundationVersionNumber10_4 567.00 #define NSFoundationVersionNumber10_4_1 567.00 #define NSFoundationVersionNumber10_4_2 567.12 #define NSFoundationVersionNumber10_4_3 567.21 #define NSFoundationVersionNumber10_4_4_Intel 567.23 #define NSFoundationVersionNumber10_4_4_PowerPC 567.21 #define NSFoundationVersionNumber10_4_5 567.25 #define NSFoundationVersionNumber10_4_6 567.26 #define NSFoundationVersionNumber10_4_7 567.27 #define NSFoundationVersionNumber10_4_8 567.28 #define NSFoundationVersionNumber10_4_9 567.29 #define NSFoundationVersionNumber10_4_10 567.29 #define NSFoundationVersionNumber10_4_11 567.36 #define NSFoundationVersionNumber10_5 677.00 #define NSFoundationVersionNumber10_5_1 677.10 #define NSFoundationVersionNumber10_5_2 677.15 #define NSFoundationVersionNumber10_5_3 677.19 #define NSFoundationVersionNumber10_5_4 677.19 #define NSFoundationVersionNumber10_5_5 677.21 #define NSFoundationVersionNumber10_5_6 677.22 #define NSFoundationVersionNumber10_5_7 677.24 #define NSFoundationVersionNumber10_5_8 677.26 #define NSFoundationVersionNumber10_6 751.00 #define NSFoundationVersionNumber10_6_1 751.00 #define NSFoundationVersionNumber10_6_2 751.14 #define NSFoundationVersionNumber10_6_3 751.21 #define NSFoundationVersionNumber10_6_4 751.29 #define NSFoundationVersionNumber10_6_5 751.42 #define NSFoundationVersionNumber10_6_6 751.53 #define NSFoundationVersionNumber10_6_7 751.53 #define NSFoundationVersionNumber10_6_8 751.62 #define NSFoundationVersionNumber10_7 833.10 #define NSFoundationVersionNumber10_7_1 833.10 #define NSFoundationVersionNumber10_7_2 833.20 #define NSFoundationVersionNumber10_7_3 833.24 #define NSFoundationVersionNumber10_7_4 833.25 #define NSFoundationVersionNumber10_8 945.00 #define NSFoundationVersionNumber10_8_1 945.00 #define NSFoundationVersionNumber10_8_2 945.11 #define NSFoundationVersionNumber10_8_3 945.16 #define NSFoundationVersionNumber10_8_4 945.18 #define NSFoundationVersionNumber10_9 1056 #define NSFoundationVersionNumber10_9_1 1056 #define NSFoundationVersionNumber10_9_2 1056.13 #define NSFoundationVersionNumber10_10 1151.16 #define NSFoundationVersionNumber10_10_1 1151.16 #define NSFoundationVersionNumber10_10_2 1152.14 #define NSFoundationVersionNumber10_10_3 1153.20 #endif #if TARGET_OS_IPHONE #define NSFoundationVersionNumber_iPhoneOS_2_0 678.24 #define NSFoundationVersionNumber_iPhoneOS_2_1 678.26 #define NSFoundationVersionNumber_iPhoneOS_2_2 678.29 #define NSFoundationVersionNumber_iPhoneOS_3_0 678.47 #define NSFoundationVersionNumber_iPhoneOS_3_1 678.51 #define NSFoundationVersionNumber_iPhoneOS_3_2 678.60 #define NSFoundationVersionNumber_iOS_4_0 751.32 #define NSFoundationVersionNumber_iOS_4_1 751.37 #define NSFoundationVersionNumber_iOS_4_2 751.49 #define NSFoundationVersionNumber_iOS_4_3 751.49 #define NSFoundationVersionNumber_iOS_5_0 881.00 #define NSFoundationVersionNumber_iOS_5_1 890.10 #define NSFoundationVersionNumber_iOS_6_0 992.00 #define NSFoundationVersionNumber_iOS_6_1 993.00 #define NSFoundationVersionNumber_iOS_7_0 1047.20 #define NSFoundationVersionNumber_iOS_7_1 1047.25 #define NSFoundationVersionNumber_iOS_8_0 1140.11 #define NSFoundationVersionNumber_iOS_8_1 1141.1 #define NSFoundationVersionNumber_iOS_8_2 1142.14 #define NSFoundationVersionNumber_iOS_8_3 1144.17 #define NSFoundationVersionNumber_iOS_8_4 1144.17 #endif
回到代码第6行,对版本进行比较,这里必须是运行时代码,如果是iOS7之前就调用旧的方法,否则使用iOS7之后的替代方案。
第8行是忽略使用了已销毁定义的编译警告。
其他的方案讨论,请看.so中的讨论:http://stackoverflow.com/questions/3339722/how-to-check-ios-version/