熟悉CADisplayLink和NSTimer

一昨登、什么是CADisplayLink

簡(jiǎn)單地說,它就是一個(gè)定時(shí)器贯底,每隔幾毫秒刷新一次屏幕丰辣。
CADisplayLink是一個(gè)能讓我們以和屏幕刷新率相同的頻率將內(nèi)容畫到屏幕上的定時(shí)器。我們?cè)趹?yīng)用中創(chuàng)建一個(gè)新的 CADisplayLink 對(duì)象丈甸,把它添加到一個(gè)runloop中糯俗,并給它提供一個(gè) target 和 selector 在屏幕刷新的時(shí)候調(diào)用尿褪。
一但 CADisplayLink 以特定的模式注冊(cè)到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對(duì)象在動(dòng)畫的下一幀要更新的大小等等。
在添加進(jìn)runloop的時(shí)候我們應(yīng)該選用高一些的優(yōu)先級(jí)囤采,來保證動(dòng)畫的平滑述呐。可以設(shè)想一下蕉毯,我們?cè)趧?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)畫不流暢江掩。

CADisplayLink的屬性介紹:

1.duration屬性:提供了每幀之間的時(shí)間,也就是屏幕每次刷新之間的的時(shí)間。該屬性在target的selector被首次調(diào)用以后才會(huì)被賦值环形。selector的調(diào)用間隔時(shí)間計(jì)算方式是:時(shí)間=duration×frameInterval策泣。 我們可以使用這個(gè)時(shí)間來計(jì)算出下一幀要顯示的UI的數(shù)值。但是 duration只是個(gè)大概的時(shí)間斟赚,如果CPU忙于其它計(jì)算着降,就沒法保證以相同的頻率執(zhí)行屏幕的繪制操作,這樣會(huì)跳過幾次調(diào)用回調(diào)方法的機(jī)會(huì)拗军。
2.frameInterval屬性:是可讀可寫的NSInteger型值任洞,標(biāo)識(shí)間隔多少幀調(diào)用一次selector 方法,默認(rèn)值是1发侵,即每幀都調(diào)用一次交掏。如果每幀都調(diào)用一次的話,對(duì)于iOS設(shè)備來說那刷新頻率就是60HZ也就是每秒60次刃鳄,如果將 frameInterval 設(shè)為2 那么就會(huì)兩幀調(diào)用一次盅弛,也就是變成了每秒刷新30次。
3.pause屬性:控制CADisplayLink的運(yùn)行叔锐。當(dāng)我們想結(jié)束一個(gè)CADisplayLink的時(shí)候挪鹏,應(yīng)該調(diào)用-(void)invalidate 從runloop中刪除并刪除之前綁定的 target 跟 selector
4.timestamp屬性: 只讀的CFTimeInterval值,表示屏幕顯示的上一幀的時(shí)間戳愉烙,這個(gè)屬性通常被target用來計(jì)算下一幀中應(yīng)該顯示的內(nèi)容讨盒。 打印timestamp值,其樣式類似于:179699.631584步责。

另外 CADisplayLink 不能被繼承返顺。

給非UI對(duì)象添加動(dòng)畫效果
我們知道動(dòng)畫效果就是一個(gè)屬性的線性變化,比如 UIView 動(dòng)畫的 EasyIn EasyOut 蔓肯。通過數(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ǎn)單的。

二旧噪、CADisplayLink 與 NSTimer 有什么不同?

1.原理不同

CADisplayLink是一個(gè)能讓我們以和屏幕刷新率同步的頻率將特定的內(nèi)容畫到屏幕上的定時(shí)器類吨娜。 CADisplayLink以特定模式注冊(cè)到runloop后, 每當(dāng)屏幕顯示內(nèi)容刷新結(jié)束的時(shí)候淘钟,runloop就會(huì)向 CADisplayLink指定的target發(fā)送一次指定的selector消息宦赠, CADisplayLink類對(duì)應(yīng)的selector就會(huì)被調(diào)用一次。
NSTimer以指定的模式注冊(cè)到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è)定号俐,相對(duì)就靈活的多。

3定庵、精確度不同

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í)間的延遲范圍绎晃。

4蜜唾、使用場(chǎng)景

CADisplayLink使用場(chǎng)合相對(duì)專一杂曲,適合做UI的不停重繪庶艾,比如自定義動(dòng)畫引擎或者視頻播放的渲染。
NSTimer的使用范圍要廣泛的多擎勘,各種需要單次或者循環(huán)定時(shí)處理的任務(wù)都可以使用咱揍。

三、CADisplayLink和NSTimer的使用方法

  • CADisplayLink的使用
    1.創(chuàng)建方法
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    2.停止方法
    [self.displayLink invalidate];
    self.displayLink = nil;
    當(dāng)把CADisplayLink對(duì)象add到runloop中后棚饵,selector就能被周期性調(diào)用煤裙,類似于重復(fù)的NSTimer被啟動(dòng)了;執(zhí)行invalidate操作時(shí)噪漾,CADisplayLink對(duì)象就會(huì)從runloop中移除硼砰,selector調(diào)用也隨即停止,類似于NSTimer的invalidate方法欣硼。

  • NSTimer的使用

    1. 創(chuàng)建方法
      NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action:) userInfo:nil repeats:NO];
      TimerInterval : 執(zhí)行之前等待的時(shí)間题翰。比如設(shè)置成1.0,就代表1秒后執(zhí)行方法
      target : 需要執(zhí)行方法的對(duì)象。
      selector : 需要執(zhí)行的方法
      repeats : 是否需要循環(huán)
  1. 釋放方法
    [timer invalidate];
    注意 :調(diào)用創(chuàng)建方法后豹障,target對(duì)象的計(jì)數(shù)器會(huì)加1冯事,直到執(zhí)行完畢,自動(dòng)減1血公。如果是循環(huán)執(zhí)行的話昵仅,就必須手動(dòng)關(guān)閉,否則可以不執(zhí)行釋放方法累魔。

  2. 特性
    存在延遲 摔笤,不管是一次性的還是周期性的timer的實(shí)際觸發(fā)事件的時(shí)間,都會(huì)與所加入的RunLoop和RunLoop Mode有關(guān)垦写,如果此RunLoop正在執(zhí)行一個(gè)連續(xù)性的運(yùn)算籍茧,timer就會(huì)被延時(shí)出發(fā)。重復(fù)性的timer遇到這種情況梯澜,如果延遲超過了一個(gè)周期寞冯,則會(huì)在延時(shí)結(jié)束后立刻執(zhí)行,并按照之前指定的周期繼續(xù)執(zhí)行晚伙。
    注意:必須加入Runloop
    使用上面的創(chuàng)建方式吮龄,會(huì)自動(dòng)把timer加入MainRunloop的NSDefaultRunLoopMode中。如果使用以下方式創(chuàng)建定時(shí)器咆疗,就必須手動(dòng)加入Runloop:
    NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末漓帚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子午磁,更是在濱河造成了極大的恐慌尝抖,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件迅皇,死亡現(xiàn)場(chǎng)離奇詭異昧辽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)登颓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門搅荞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人框咙,你說我怎么就攤上這事咕痛。” “怎么了喇嘱?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵茉贡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我者铜,道長(zhǎng)腔丧,這世上最難降的妖魔是什么构蹬? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮悔据,結(jié)果婚禮上庄敛,老公的妹妹穿的比我還像新娘。我一直安慰自己科汗,他們只是感情好藻烤,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著头滔,像睡著了一般怖亭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坤检,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天兴猩,我揣著相機(jī)與錄音,去河邊找鬼早歇。 笑死倾芝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的箭跳。 我是一名探鬼主播晨另,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼谱姓!你這毒婦竟也來了借尿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤屉来,失蹤者是張志新(化名)和其女友劉穎路翻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茄靠,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茂契,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嘹黔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片账嚎。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡莫瞬,死狀恐怖儡蔓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疼邀,我是刑警寧澤匆赃,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布窗市,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜墓律,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梢薪,春花似錦、人聲如沸尝哆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秋泄。三九已至琐馆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恒序,已是汗流浹背瘦麸。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歧胁,地道東北人滋饲。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像喊巍,于是被迫代替她去往敵國(guó)和親了赌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容