iOS10 再談CAAnimationDelegate相關(guān)協(xié)議的適配

前言

之前寫過這樣一篇文章:

iOS10 CAAnimationDelegate的簡單適配

文中提到了在iOS10中,關(guān)于系統(tǒng)API里CAAnimationDelegate協(xié)議的一些變化以及一種較為妥協(xié)的的適配寫法。此文是基于上文的一個(gè)補(bǔ)充和完善,并提出一些相對(duì)更為完善的寫法。
為了方便和節(jié)省大家的時(shí)間,先在此直接給出下文中提到的一種最簡單的寫法,對(duì)于探究過程沒有興趣的可以直接忽略下文(但是還是強(qiáng)烈建議看看,一方面這么寫一項(xiàng)都不能缺省是有重要原因的,另一方面如果你還有其他想法,歡迎據(jù)此給出指正或建議)

#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

1.起因

寫這篇文章的起因是前陣子在寫一個(gè)demo時(shí),用到了CALayerDelegate的相關(guān)協(xié)議方法,并遇到了和CAAnimationDelegate一樣的情況,警告。
查看API,也看到了類似的變化:

iOS10以后的CALayerDelegate(截圖自xcode8.1相關(guān)API)

再對(duì)比下10以前的:

iOS10之前的CALayerDelegate(截圖自xcode7.3.1相關(guān)API)

同樣的變化,由基類的分類這種非正式協(xié)議,變成了正式的協(xié)議聲明。再看下這個(gè)代理的前后變化:

iOS10以后
iOS10之前

本來也是直接按照之前的方式來解決這個(gè)警告的,但是細(xì)想下來,不知道這樣的變化還有多少,只是目前遇到的,都只是QuartzCore框架下的。這或許是蘋果在規(guī)范自己的API?

2.關(guān)于這里的適配

這里說的適配,并不是像適配某一個(gè)方法是否兼容某一系統(tǒng)版本那樣的適配,因?yàn)槟欠N版本適配不做的話,影響的是APP的兼容性。而這里的適配,并不會(huì)影響APP的兼容性,有試過直接用低版本真機(jī)編譯這些未經(jīng)適配的協(xié)議代碼,執(zhí)行并不會(huì)有什么影響。具體機(jī)理我并不能說太清楚,但是畢竟這只是一種針對(duì)原有API的修改,而不是新增。(其實(shí)我一直是很好奇像NS_AVAILABLE_IOS這類相關(guān)的宏標(biāo)示的方法和其指定的低版本系統(tǒng)不兼容的原因,是系統(tǒng)執(zhí)行這些代碼時(shí)會(huì)遇到什么問題嗎?求解。)

那么做這樣的適配意義又何在?
開發(fā)兼容。

一個(gè)團(tuán)隊(duì)協(xié)作開發(fā),可能因?yàn)楦鞣N原因,每個(gè)人的xcode版本并不能保持一致(適配iOS7及以下的機(jī)器用xcode8調(diào)試不了、低版本系統(tǒng)的mac裝不了新的xcode……)。
還有就是我們?cè)趯懸恍╅_源三方時(shí),不做這樣的兼容適配,有些使用低版本xcode的開發(fā)者,在使用你的代碼時(shí),可能會(huì)因此報(bào)錯(cuò),從而造成一些不必要的麻煩。

3.更好的適配寫法

這里的更好,是相對(duì)之前那篇文章來的。
之前那樣寫,是因?yàn)椴荒艽_定開發(fā)者xcode版本,從而不能直接使用__IPHONE_10_0這類宏。

3.1.嘗試的方案一

#if (__IPHONE_OS_VERSION_MAX_ALLOWED == __IPHONE_10_0) || (__IPHONE_OS_VERSION_MAX_ALLOWED == __IPHONE_10_1)
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

既然不能確定__IPHONE_10_0宏是否存在,從而不能直接寫__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0這樣的判定語句(因?yàn)槿?code>__IPHONE_10_0宏不存在,這個(gè)邏輯恒成立從而無效),那么改為判等應(yīng)該就沒問題了,可惜因?yàn)?0.1也出來了,只能增加或邏輯。不過,這樣做,同樣帶來了維護(hù)的代價(jià),系統(tǒng)肯定是要持續(xù)迭代的,每次迭代都要新增或條件,這樣做麻煩不說,風(fēng)險(xiǎn)也是遠(yuǎn)大于之前的做法的。。。

3.2.改進(jìn)的方案二

#ifdef __IPHONE_10_0
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

既然是因?yàn)闊o法判斷__IPHONE_10_0宏是否存在,那么就以此為條件豈不是正好?而且這類宏是隨版本迭代持續(xù)遞增的,那么只要__IPHONE_10_0存在,應(yīng)該就可以確認(rèn)xcode版本至少是8,畢竟__IPHONE_10_1肯定是之后出現(xiàn)的。
然而,經(jīng)過實(shí)際實(shí)驗(yàn)……在xcode7.3.1上依舊報(bào)錯(cuò):CALayerDelegate協(xié)議不存在,#ifdef條件分支依舊參與編譯了……why???
首先這樣的邏輯應(yīng)該是沒問題的,那就查看xcode7.3.1的API吧。果然,在CABase.h文件中發(fā)現(xiàn)了這樣的一段定義:

xcode7.3.1中CABase.h文件中的一段定義

什么鬼???9.3.1還要涉及10.0了?難怪之前的條件可以成立……
再次翻看xcode8.1中關(guān)于CABase.h中的相關(guān)部分,好嘛,這些已經(jīng)全都沒有了,整個(gè)頭文件的宏定義改了一大半,基本“面目全非”了,果然是善變啊……

3.3.完善的方案三

有了之前兩次嘗試,方案三應(yīng)運(yùn)而生,也就是文章開頭的那個(gè)了:

#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

這就是為什么開頭有提到,一項(xiàng)都不能缺省,否則后果見方案二。
這里除了判斷__IPHONE_10_0宏是否定義,還判斷了當(dāng)前系統(tǒng)的版本是否是大于10.0的,其實(shí)主要是為了判斷xcode的版本是否是大于8.0的(第2部分提到的開發(fā)適配)。
#if defined(__IPHONE_10_0)這個(gè)等效于#if defined __IPHONE_10_0,也就是我們通常寫的#ifdef __IPHONE_10_0的簡化后的單條件版本,用#if defined更為靈活,可以判斷多個(gè)條件。
當(dāng)然這里也可以根據(jù)習(xí)慣拆開寫,即先寫#ifdef __IPHONE_10_0,再寫#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0,只是多了幾步,意思相同。

至此,針對(duì)這部分的適配結(jié)束了。最終的方案應(yīng)該是較為完善的了,目前也沒有想到更合適的了。實(shí)際使用測(cè)試,還沒有發(fā)現(xiàn)什么問題,如果你遇到了,歡迎及時(shí)反饋。

參考文章:
1.C語言的條件編譯#if, #elif, #else, #endif、#ifdef, #ifndef
2.#if、#ifdef、#if defined之間的區(qū)別
3.#if defined和#if !defined(c語言的宏定義)

·轉(zhuǎn)載請(qǐng)聲明·

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 因?yàn)橐Y(jié)局swift3.0中引用snapKit的問題,看到一篇介紹Xcode8,swift3變化的文章,覺得很詳細(xì)...
    uniapp閱讀 4,877評(píng)論 0 12
  • 一.iPhone X尺寸問題 1. 高度增加了145pt,變成812pt. 2.屏幕圓角顯示,注意至少留10pt邊...
    騎行天下閱讀 13,259評(píng)論 5 36
  • 1.尺寸適配1.原因 iOS7中所有導(dǎo)航欄都為半透明,導(dǎo)航欄(height=44)和狀態(tài)欄(height=20)不...
    LZM輪回閱讀 6,390評(píng)論 1 4
  • 曾經(jīng)有一段時(shí)間,我的工作非常忙碌,忙到除了睡覺吃飯的時(shí)間,其他時(shí)間都在工作。而且為了最高效地處理工作,防止工...
    妙貝閱讀 959評(píng)論 0 1
  • 正確寫法應(yīng)該是:弗洛伊德 弗洛伊德生平 作為一個(gè)治療精神疾病的醫(yī)生,弗洛伊德創(chuàng)立了一個(gè)涉及人類心理結(jié)構(gòu)和功能的學(xué)說...
    昭的私房家伙閱讀 623評(píng)論 0 0

友情鏈接更多精彩內(nèi)容