SDK兼容性的代码

来源:互联网 发布:绿色上网软件 编辑:程序博客网 时间:2024/04/24 05:59
让代码满足兼容性的要求,需要学习下面4项:
1. 类、方法、函数、framework的链接要使用“弱”的。
2. 对不同版本的SDK使用“条件编译”。
3. 注意废弃的API。
4. 在runtime,检查系统的版本、framework的版本。

● 类的“弱链接”。
使用弱链接的类,程序员必须在runtime检查该类是否存在。不事先检查而直接使用,会导致一个runtime binding error,从而终止程序。

检查的最简单的方法是使用“[NSObject class]”方法。但有四个前提:
1> 在写代码时,你先要检查,类的framework是否支持“NS_CLASS_AVAILABLE”宏
2> 工程设置里,base SDK 必须是 iOS 4.2+。<SDKROOT : Base SDK>
3> 对设备的要求,必须是 iOS 3.1+。<IPHONEOS_DEPLOYMENT_TARGET : IOS Deployment Target>
4> 使用的编译器:LLVM-GCC 4.2+、LLVM compiler (Clang) 1.5+

编译示例:
if ([UIPrintInteractionController class]) {
    // 可以创建其实例
} else {
    // 不支持。想别的辙吧
}

若某iOS工程不能满足上述四个前提,有个替代方案:NSClassFromString。看示例:
Class cls = NSClassFromString (@"NSRegularExpression");
if (cls) {
    // 可以创建其实例
} else {
    // 不支持。想别的辙吧
}

● 成员函数的“弱链接”。示例:
if ([UIImagePickerController instancesRespondToSelector:@selector (availableCaptureModesForCameraDevice:)]) {
    // 可以使用该成员函数
} else {
    // 不支持。想别的辙吧
}

● C函数的“弱链接”。示例:
if (CGColorCreateGenericCMYK != NULL) {
    CGColorCreateGenericCMYK (0.1,0.5.0.0,1.0,0.1);
} else {
    // 不支持。想别的辙吧
}

警告:必须使用“NULL或nil”进行比较,不能使用操作符“!”求地址的负。

● 多个Base SDK的共存之道:条件编译。
若你的代码要使用多个Base SDK,则必须使用“条件编译”。这就要用到Availability.h里面预定义的一些宏。
在Xcode里,选择File -> Open Quickly,打开Availability.h文件。可以看到这些预定义宏。

示例:

上面的函数 CGColorCreateGenericCMYK 是在Mac OS X v10.5提供的。
假设,很不幸,你安装的Xcode只给你提供了macosx10.4的SDK,怎么办?为了编译通过,把这段代码注释掉吗?

不用的。你只需要用预定义宏即可。
好处是,以后你升级了SDK,或者把该工程拿给别人,一样可以编译,无需任何修改。

#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED            // 使用Mac OS X的SDK,而非iOS SDK
#    if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050    // 绝对不能使用__MAC_10_5,而要用数字
        if (CGColorCreateGenericCMYK != NULL) {
            CGColorCreateGenericCMYK(0.1,0.5.0.0,1.0,0.1);
        } else {
#    endif
            // 不支持。想别的辙吧
#    if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
        }
#    endif
#endif

__MAC_OS_X_VERSION_MAX_ALLOWED 这个宏由你的Base SDK来自动设置。


对于iOS,对应的宏为:__IPHONE_OS_VERSION_MAX_ALLOWED。

● 对设备的最低版本也用条件编译来区分
在Xcode工程里,设置了“iOS Deployment Target”之后,另外一个宏也就有了值:__IPHONE_OS_VERSION_MIN_REQUIRED。
同上,若你对最低版本也有多个要求,则可使用该宏来做区分。


● 废弃的API
API被标志为“废弃”,意味着不久的将来,该API将消失。虽然不是马上消失,还是要注意的。因为,与“废弃”相伴的,肯定是功能更完善的API的出现。
使用新的API替换废弃的API,这是苹果推荐的作法。
可以使用deprecated关键字搜索你的Build log,即可找到关于废弃API的警告。

● 在运行时检查系统的版本
有时,一个函数会在不同版本的设备上有不同的表现。这时,只检查该API的有无就不能满足要求了。
在iOS设备上,用下面的代码:
NSString *osVersion = [[UIDevice currentDevice] systemVersion];

● 在runtime检查framework的版本
许多framework都可在runtime检查版本,比如Application Kit,可使用NSAppKitVersionNumber。示例:

if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_0) {
    // [*, 10.0]
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) {
    // (10.0, 10.1]
} else {
    // (10.1, *)
}