CADisplayLink的基礎 以及CADisplayLink與NSTimer的比較

上次分享過一片關于NSTimer的知識,略有感觸,然而與NSTimer有類似功能效果的還有一個控件CADisplayLink,長話短說,下面會對CADisplayLink進行一個簡單而又系統的了解...

1: 什么是CADisplsyLink?

1)在屏幕刷新的時候使用:
CADisplayLink是一個能讓我們以和屏幕刷新率同步的頻率將特定的內容畫到屏幕上的定時器類。CADisplayLink以特定模式注冊到runloop后,每當屏幕顯示內容刷新結束的時候,runloop就會向CADisplayLink指定的target發送一次指定的selector消息, CADisplayLink類對應的selector就會被調用一次。所以通常情況下,按照iOS設備屏幕的刷新率60次/秒(CADisplayLink 默認每秒運行60次,將它的frameInterval屬性設置為2,意味CADisplayLink每隔一幀運行一次,有效的使游戲邏輯每秒運行30次)

2)延遲
iOS設備的屏幕刷新頻率是固定的,CADisplayLink在正常情況下會在每次刷新結束都被調用,精確度相當高。但如果調用的方法比較耗時,超過了屏幕刷新周期,就會導致跳過若干次回調調用機會。如果CPU過于繁忙,無法保證屏幕60次/秒的刷新率,就會導致跳過若干次調用回調方法的機會,跳過次數取決CPU的忙碌程度。

3)使用場景
CADisplayLink適合做界面的不停重繪,比如視頻播放的時候需要不停地獲取下一幀用于界面渲染。

2: 代碼分析
#import "CADisplayLinkController.h"

#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height

@interface CADisplayLinkController ()

@property (nonatomic,strong) CADisplayLink* CADisplayLink;
@property (nonatomic,strong) UIButton* button;

@end

@implementation CADisplayLinkController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view addSubview:self.button];
}

-(void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if (_CADisplayLink)
    {
        [_CADisplayLink invalidate];
        _CADisplayLink = nil;
    }
}

-(UIButton*) button
{
    if (!_button)
    {
        _button = [UIButton buttonWithType:UIButtonTypeCustom];
        _button.frame = CGRectMake(SCREEN_WIDTH / 2 - 100, SCREEN_HEIGHT / 2, 200, 40);
        _button.backgroundColor = [UIColor redColor];
        _button.layer.cornerRadius = 5;
        [_button setTitle:@"點擊" forState:UIControlStateNormal];
        [_button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _button;
}

-(CADisplayLink*) CADisplayLink
{
    if (!_CADisplayLink)
    {
        /*創建一個_CADisplayLink對象,然后在target上綁定selector*/
        _CADisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(startDisplayLink:)];
        [_CADisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; /*將_CADisplayLink加入到RunLoop里面之后,selector就會被周期性的調用*/
    }
    return _CADisplayLink;
}

#pragma mark - 點擊button
-(void) clickAction:(UIButton*) sender
{
    [self CADisplayLink];
}

#pragma mark - 開始繪制
-(void) startDisplayLink:(id) sender
{
    NSLog(@"startDisplayLink");
}

#pragma mark - touch屏幕,取消相應事件
-(void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [_CADisplayLink invalidate]; /*將CADisplayLink從RunLoop中移除,selector的調用也會停止*/
    _CADisplayLink = nil; /*銷毀CADisplayLink, 這樣可以避免控制器不死*/
}
3:細節點
1) 關于暫停和開啟設置
-(void) viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    _CADisplayLink.paused = NO; /*開啟, 類似于NSTimer的distantPast屬性*/
}

-(void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    _CADisplayLink.paused = YES; /*暫停屬性,類似于NSTimer的distantFuture*/
}
2)  關于NSRunLoopMode
  
    NSDefaultRunLoopModel:監聽用戶最基本的操作(點擊,觸摸等)
    NSRunLoopCommonModels:監聽一些特殊操作:滾動等
    那么,為什么在NSDefaultRunLoopModel模式下發生滾動,計時器會停止?那是因為系統認為,用戶不應該邊滾動邊操作界面,所以停止了(觸碰,點擊等)NSDefaultRunLoopModel模式下監聽的事件
4:CADisplayLink與NSTimer之間的差異

1)精確度
iOS設備的屏幕刷新頻率是固定的,CADisplayLink在正常情況下會在每次刷新結束都被調用,精確度相當高。NSTimer的精確度就顯得低了點,比如NSTimer的觸發時間到的時候,runloop如果在阻塞狀態,觸發時間就會推遲到下一個runloop周期。并且NSTimer新增了tolerance屬性,讓用戶可以設置可以容忍的觸發的時間的延遲范圍。

2)使用場合
CADisplayLink使用場合相對專一,適合做UI的不停重繪,比如自定義動畫引擎或者視頻播放的渲染。NSTimer的使用范圍要廣泛的多,各種需要單次或者循環定時處理的任務都可以使用,比如用在背景計算,更新一些數值資料。在UI相關的動畫或者顯示內容使用 CADisplayLink比起用NSTimer的好處就是我們不需要在格外關心屏幕的刷新頻率了,因為它本身就是跟屏幕刷新同步的。

  1. 上面的一些基礎知識,一些是自己在網上百度整合的,大概整理一下,關于如上的知識,幾乎看完這些,差不多能有個大差不差的理解,謝謝您的閱讀

參考知識:
NSRunLoopMode解析
NSTimer基礎
官方文檔
Core Animation系列之CADisplayLink

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內容