由于系统平台和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 pop11 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中的讨论: