SDK兼容性的代碼

讓代碼滿足兼容性的要求,需要學習下面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, *)
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章