CADisplayLink
是一個(gè)能讓我們以和屏幕刷新率相同的頻率將內(nèi)容畫到屏幕上的定時(shí)器寸癌。我們在應(yīng)用中創(chuàng)建一個(gè)新的 CADisplayLink
對象,把它添加到一個(gè)runloop
中戚长,并給它提供一個(gè) target
和selector
在屏幕刷新的時(shí)候調(diào)用。
一但 CADisplayLink
以特定的模式注冊到runloop
之后,每當(dāng)屏幕需要刷新的時(shí)候,runloop
就會(huì)調(diào)用CADisplayLink
綁定的target
上的selector
圆存,這時(shí)target
可以讀到 CADisplayLink
的每次調(diào)用的時(shí)間戳,用來準(zhǔn)備下一幀顯示需要的數(shù)據(jù)仇哆。例如一個(gè)視頻應(yīng)用使用時(shí)間戳來計(jì)算下一幀要顯示的視頻數(shù)據(jù)沦辙。在UI做動(dòng)畫的過程中,需要通過時(shí)間戳來計(jì)算UI對象在動(dòng)畫的下一幀要更新的大小等等讹剔。
在添加進(jìn)runloop
的時(shí)候我們應(yīng)該選用高一些的優(yōu)先級(jí)油讯,來保證動(dòng)畫的平滑⊙忧罚可以設(shè)想一下陌兑,我們在動(dòng)畫的過程中,runloop
被添加進(jìn)來了一個(gè)高優(yōu)先級(jí)的任務(wù)由捎,那么兔综,下一次的調(diào)用就會(huì)被暫停轉(zhuǎn)而先去執(zhí)行高優(yōu)先級(jí)的任務(wù),然后在接著執(zhí)行CADisplayLink
的調(diào)用狞玛,從而造成動(dòng)畫過程的卡頓软驰,使動(dòng)畫不流暢。
duration
屬性提供了每幀之間的時(shí)間心肪,也就是屏幕每次刷新之間的的時(shí)間锭亏。我們可以使用這個(gè)時(shí)間來計(jì)算出下一幀要顯示的UI的數(shù)值。但是 duration
只是個(gè)大概的時(shí)間硬鞍,如果CPU忙于其它計(jì)算慧瘤,就沒法保證以相同的頻率執(zhí)行屏幕的繪制操作,這樣會(huì)跳過幾次調(diào)用回調(diào)方法的機(jī)會(huì)固该。
frameInterval
屬性是可讀可寫的NSInteger
型值碑隆,標(biāo)識(shí)間隔多少幀調(diào)用一次selector
方法,默認(rèn)值是1蹬音,即每幀都調(diào)用一次上煤。如果每幀都調(diào)用一次的話,對于iOS設(shè)備來說那刷新頻率就是60HZ也就是每秒60次著淆,如果將 frameInterval
設(shè)為2 那么就會(huì)兩幀調(diào)用一次劫狠,也就是變成了每秒刷新30次。
我們通過pause
屬性開控制CADisplayLink
的運(yùn)行永部。當(dāng)我們想結(jié)束一個(gè)CADisplayLink
的時(shí)候独泞,應(yīng)該調(diào)用-(void)invalidate
從runloop
中刪除并刪除之前綁定的 target
跟selector
另外CADisplayLink
不能被繼承。
CADisplayLink
與 NSTimer
有什么不同
iOS設(shè)備的屏幕刷新頻率是固定的苔埋,CADisplayLink
在正常情況下會(huì)在每次刷新結(jié)束都被調(diào)用懦砂,精確度相當(dāng)高。
NSTimer
的精確度就顯得低了點(diǎn),比如NSTimer
的觸發(fā)時(shí)間到的時(shí)候荞膘,runloop
如果在阻塞狀態(tài)罚随,觸發(fā)時(shí)間就會(huì)推遲到下一個(gè)runloop
周期。并且 NSTimer
新增了tolerance
屬性羽资,讓用戶可以設(shè)置可以容忍的觸發(fā)的時(shí)間的延遲范圍淘菩。
CADisplayLink
使用場合相對專一,適合做UI的不停重繪屠升,比如自定義動(dòng)畫引擎或者視頻播放的渲染潮改。NSTimer
的使用范圍要廣泛的多,各種需要單次或者循環(huán)定時(shí)處理的任務(wù)都可以使用腹暖。在UI相關(guān)的動(dòng)畫或者顯示內(nèi)容使用 CADisplayLink
比起用NSTimer
的好處就是我們不需要在格外關(guān)心屏幕的刷新頻率了汇在,因?yàn)樗旧砭褪歉聊凰⑿峦降摹?/p>
CADisplayLink使用的例子
給非UI對象添加動(dòng)畫效果
我們知道動(dòng)畫效果就是一個(gè)屬性的線性變化,比如UIView 動(dòng)畫的 EasyInEasyOut 脏答。通過數(shù)值按照不同速率的變化我們能生成更接近真實(shí)世界的動(dòng)畫效果趾疚。我們也可以利用這個(gè)特性來使一些其他屬性按照我們期望的曲線變化。比如當(dāng)播放視頻時(shí)關(guān)掉視頻的聲音我可以通過CADisplayLink
來實(shí)現(xiàn)一個(gè) EasyOut的漸出效果:先快速的降低音量以蕴,在慢慢的漸變到靜音糙麦。
注意
通常來講:iOS設(shè)備的刷新頻率事60HZ也就是每秒60次。那么每一次刷新的時(shí)間就是1/60秒 大概16.7毫秒丛肮。當(dāng)我們的frameInterval
值為1的時(shí)候我們需要保證的是 CADisplayLink
調(diào)用的`target`的函數(shù)計(jì)算時(shí)間不應(yīng)該大于 16.7否則就會(huì)出現(xiàn)嚴(yán)重的丟幀現(xiàn)象赡磅。
在mac應(yīng)用中我們使用的不是CADisplayLink
而是 CVDisplayLink
它是基于C接口的用起來配置有些麻煩但是用起來還是很簡單的。
下面結(jié)合NSTimer來介紹 CADisplayLink宝与,與NSTimer不同的地方有:
1焚廊、原理不同
CADisplayLink是一個(gè)能讓我們以和屏幕刷新率同步的頻率將特定的內(nèi)容畫到屏幕上的定時(shí)器類。 CADisplayLink以特定模式注冊到runloop后习劫, 每當(dāng)屏幕顯示內(nèi)容刷新結(jié)束的時(shí)候咆瘟,runloop就會(huì)向 CADisplayLink指定的target發(fā)送一次指定的selector消息, CADisplayLink類對應(yīng)的selector就會(huì)被調(diào)用一次诽里。
NSTimer以指定的模式注冊到runloop后袒餐,每當(dāng)設(shè)定的周期時(shí)間到達(dá)后,runloop會(huì)向指定的target發(fā)送一次指定的selector消息谤狡。
2灸眼、周期設(shè)置方式不同
iOS設(shè)備的屏幕刷新頻率(FPS)是60Hz,因此CADisplayLink的selector 默認(rèn)調(diào)用周期是每秒60次墓懂,這個(gè)周期可以通過frameInterval屬性設(shè)置焰宣, CADisplayLink的selector每秒調(diào)用次數(shù)=60/ frameInterval。比如當(dāng) frameInterval設(shè)為2捕仔,每秒調(diào)用就變成30次匕积。因此盈罐, CADisplayLink 周期的設(shè)置方式略顯不便。
NSTimer的selector調(diào)用周期可以在初始化時(shí)直接設(shè)定闪唆,相對就靈活的多盅粪。
3、精確度不同
iOS設(shè)備的屏幕刷新頻率是固定的苞氮,CADisplayLink在正常情況下會(huì)在每次刷新結(jié)束都被調(diào)用,精確度相當(dāng)高瓤逼。
NSTimer的精確度就顯得低了點(diǎn)笼吟,比如NSTimer的觸發(fā)時(shí)間到的時(shí)候,runloop如果在忙于別的調(diào)用霸旗,觸發(fā)時(shí)間就會(huì)推遲到下一個(gè)runloop周期贷帮。更有甚者,在OS X v10.9以后為了盡量避免在NSTimer觸發(fā)時(shí)間到了而去中斷當(dāng)前處理的任務(wù)诱告,NSTimer新增了tolerance屬性撵枢,讓用戶可以設(shè)置可以容忍的觸發(fā)的時(shí)間范圍。
4精居、使用場合
從原理上不難看出锄禽, CADisplayLink 使用場合相對專一, 適合做界面的不停重繪靴姿,比如視頻播放的時(shí)候需要不停地獲取下一幀用于界面渲染沃但。
NSTimer的使用范圍要廣泛的多,各種需要單次或者循環(huán)定時(shí)處理的任務(wù)都可以使用佛吓。