原文: http://blog.csdn.net/wzzvictory/article/details/22417181
一、簡介
1、所在框架
CADisplayLink和其它CoreAnimation類一樣,都是在QuartzCore.framework里。
2、功能
CADisplayLink最主要的特征是能提供一個周期性的調用我們賦給它的selector的機制,從這點上看它很像定時器NSTimer。
3、使用方式
- (void)startDisplayLink { self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)]; [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } - (void)handleDisplayLink:(CADisplayLink *)displayLink { //do something } - (void)stopDisplayLink { [self.displayLink invalidate]; self.displayLink = nil; }
當把CADisplayLink對象add到runloop中后,selector就能被周期性調用,類似於NSTimer被啟動了;執行invalidate操作時, CADisplayLink對象就會從runloop中移除,selector 調用也隨即停止,類似於NSTimer的invalidate方法。
二、特性
下面結合NSTimer來介紹 CADisplayLink,與NSTimer不同的地方有:
1、原理不同
CADisplayLink是一個能讓我們以和屏幕刷新率同步的頻率將特定的內容畫到屏幕上的定時器類。 CADisplayLink以特定模式注冊到runloop后, 每當屏幕顯示內容刷新結束的時候,runloop就會向 CADisplayLink指定的target發送一次指定的selector消息, CADisplayLink類對應的selector就會被調用一次。
NSTimer以指定的模式注冊到runloop后,每當設定的周期時間到達后,runloop會向指定的target發送一次指定的selector消息。
2、周期設置方式不同
iOS設備的屏幕刷新頻率(FPS)是60Hz,因此CADisplayLink的selector 默認調用周期是每秒60次,這個周期可以通過frameInterval屬性設置, CADisplayLink的selector每秒調用次數=60/ frameInterval。比如當 frameInterval設為2,每秒調用就變成30次。因此, CADisplayLink 周期的設置方式略顯不便。
NSTimer的selector調用周期可以在初始化時直接設定,相對就靈活的多。
3、精確度不同
iOS設備的屏幕刷新頻率是固定的,CADisplayLink在正常情況下會在每次刷新結束都被調用,精確度相當高。
NSTimer的精確度就顯得低了點,比如NSTimer的觸發時間到的時候,runloop如果在忙於別的調用,觸發時間就會推遲到下一個runloop周期。更有甚者,在OS X v10.9以后為了盡量避免在NSTimer觸發時間到了而去中斷當前處理的任務,NSTimer新增了tolerance屬性,讓用戶可以設置可以容忍的觸發的時間范圍。
4、使用場合
從原理上不難看出, CADisplayLink 使用場合相對專一, 適合做界面的不停重繪,比如視頻播放的時候需要不停地獲取下一幀用於界面渲染。
NSTimer的使用范圍要廣泛的多,各種需要單次或者循環定時處理的任務都可以使用。
三、重要屬性
下面不完整的列出了 CADisplayLink的幾個重要屬性:
1、 frameInterval
可讀可寫的NSInteger型值,標識間隔多少幀調用一次selector方法,默認值是1,即每幀都調用一次。官方文檔中強調,當該值被設定小於1時,結果是不可預知的。
2、duration
只讀的CFTimeInterval值,表示兩次屏幕刷新之間的時間間隔。需要注意的是,該屬性在target的selector被首次調用以后才會被賦值。selector的調用間隔時間計算方式是:時間=duration×frameInterval。
現存的iOS設備屏幕的FPS都是60Hz,這一點可以從CADisplayLink的duration屬性看出來。duration的值都是0.166666…,即1/60。盡管如此,我們並沒法確定蘋果不會改變 FPS ,如果以后某一天將 FPS 提升到了120Hz了怎么辦呢?這時,你設置了frameInterval屬性值為2期望每秒刷新30次,卻發現每秒刷新了60次,結果可想而知,出於安全考慮,還是先根據duration判斷屏幕的 FPS再去使用CADisplayLink 。
3、timestamp
打印timestamp值,其樣式類似於:
179699.631584
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil]; NSLog("localLayerTime:%f",localLayerTime);