標籤:des android blog http io ar os 使用 for
轉載本文請保留以下原作者資訊: 原作:OneV‘s Den http://www.onevcat.com/2012/02/iosversion/
相容性,開發人員之殤
相容性問題是全世界所有開發這面臨的最頭疼的問題之一,這句話不會有開發人員會反駁。往昔的Windows Vista的升級死掉一批應用的慘狀曆曆在目,而如今火熱的移動互連網平台上類似的問題也層出不窮。Andriod的開源導致產商繁多,不同的裝置不僅硬體設定有差異,系統有差異,就連螢幕比例也有差異。想要開發出一款真正全Android平台都完美啟動並執行app簡直是不可能的.. iOS好很多,因為iPhone和iTouch的解析度完全一致(就算retina也有Apple幫你打理好了),因此需要關注的往往只有系統版本的差別。在使用到某些新系統才有的特性,或者被廢棄的方法時,都需要對運行環境做出判定。
何時需要照顧相容性
沒有人可以記住所有系統新加入的類或者屬性方法,也沒有人可以開發出一款能針對全系統的還amazing的應用。
在iOS的話,首先要做的就是為自己所開發的app選擇合適的最低版本,在XCode中的對應app的target屬性中,設定iOS Deployment Target屬性,這對應著你的app將會運行在的最低的系統版本。如果你設成iOS 4.3的話,那你就不需要考慮代碼對4.3之前的系統的相容性了——因為低於iOS 4.3的裝置是無法通過正規渠道安裝你的應用的。
但是你仍然要考慮在此之後的系統的相容性。隨著Apple不斷升級系統,有些功能或者特性在新系統版本上會有很容易很高效的實現方法,有些舊的API被廢棄或者刪除。如果沒有對這些可能存在的相容性問題做出處理的話,小則程式效率低下,之後難以維護,大則直接crash。對於這些可能存在的問題,開發人員一定要明確自己所調用的API是否存在於所用的架構中。某個類或者方法所支援的系統版本可以在官方文檔中查到,所有的條目都會有類似這樣的說明
Availability Available in iOS 5.0 and later.
或者
Availability Available in iOS 2.1 and later.
Deprecated in iOS 5.0. 從Availability即可得知版本相容的資訊。 如果iOS Deployment Target要小於系統要求,則需要另寫處理代碼,否則所使用的特性在老版本的系統上將無法表現。
另外,Apple也不過是一家公司,Apple的開發人員也不過是牛一點的程式員,iOS本身就有可能有某些bug,導致在某些版本上存在瑕疵。開發人員會很care,並儘快修正,但是很多時候使用者並不care,或者由於種種原因一直不升級系統。這時候便需要檢測系統,去避開這些bug,以增加使用者體驗了(比如3.0時的UITableView插入行時可能crash)。
符合相容性需求的代碼判定系統版本,按運行時的版本號碼運行代碼
這不一定是最有效方法,但這是最直接的方法。對系統版本的判定可以參考我的另一片文章:UIViewController的誤用。 順便在這邊也把比較的方法貼出來:
// System Versioning Preprocessor Macros#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)
使用 ··· if (SYSTEMVERSIONLESS_THAN(@“5.0”)) { //系統版本不小於5.0...Do something } ···
需要注意的是,[@“5.0” compare:@“5” options:NSNumericSearch]這樣的輸入將會返回一個NSOrderedDescending,而不是期望中的NSOrderedSame,因此在輸入的時候需要特別小心。另外這個方法的局限還在於對於4.1.3這樣的系統版本號碼比較無力,想要使用的話也許需要自己進行轉換(也許去掉第二個小數點再進行比較是個可行的方案)。
對於類,可以檢測其是否存在
如果要使用的新特性是個類,而不是某個特定的方法的話,可以用NSClassFromString來將字串轉為類,如果runtime沒有這個類的存在,該方法將返回nil。比如對於iOS 5,在位置解析方面,Apple使用了CoreLocation中的新類CLGeocoder來替代原來的MKReverseGeocoder,要判定使用哪個類,可以用下面的代碼:
if(NSClassFromString(@"CLGeocoder")) { //CLGeocoder存在,可以使用}else{ //只能使用MKReverseGeocoder}
這個方法應該是絕對靠譜的,但是只有類能夠使用。而系統更新往往帶來的不止類,也有很多新的方法和屬性這樣的東西,這個方式就無能為力了。
向特定的類或對象詢問是否擁有某特性
對於某些類活期成員,他們本身有類似詢問支不支援某種特性這樣的方法,比如大家所熟知的UIImagePickerController裡檢測可用媒體類型的availableMediaTypesForSourceType:方法,以及CMMotionManager裡檢測三軸陀螺是否可用的方法gyroAvailable。但是有些類詢問方法的類和成員所要使用的特性基本基本都是和裝置硬體有關的。
另外當然也可以用respondsToSelector:方法來檢測是否對某個方法響應。但是這是非常危險的做法,我本人不推薦使用。因為iOS系統裡存在很多私人API,而Apple的審查機制對於私人API調用的格殺勿論是業界公知的。而respondsToSelector:如果想要檢測的方法在老版本的系統中是作為私人API形式存在的話,你將得到錯誤的結果,從而去執行私人API,那就完了。這種應用往往是被拒了都不知道自己在哪兒使用了私人API…
符合iOS系統相容性需求的方法