CADisplayLink

官方API的定義是:

A timer object that allows your application to synchronize its drawing to the refresh rate of the display.

CADisplayLink是一個定時器對象,它可以讓你與屏幕刷新頻率相同的速率來刷新你的視圖。就說CADisplayLink是用于同步屏幕刷新頻率的計時器脆栋。

初始化

+ (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel

添加到runloop风题,不然不會被觸發(fā)

- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode嘁扼。

? ? ? ? 每個計時器對象只能加入到一個runloop中宙橱,但是可以被添加到不同的mode中捻悯,當(dāng)displayLink被加入到runloop時憔杨,會被runloop隱式retain鸟赫。

CADisplayLink的方法和屬性

- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode;

把指定mode的displayLink對象從runloop中移除。這個實(shí)例對象適用于想要改變實(shí)例對象的mode消别,這時候就要先從當(dāng)前mode中remove抛蚤,然后再add。這個方法會對計時器進(jìn)行隱式的release妖啥。在調(diào)用該方法時霉颠,需要做判斷,如果當(dāng)期計時器不在runloop的話荆虱,會出現(xiàn)野指針的crash蒿偎。出現(xiàn)crash的原因是runloop多次調(diào)用了release方法,進(jìn)行了over-release怀读。

- (void)invalidate;

把displayLink對象從所有runloop modes中移除诉位。執(zhí)行這個操作之后,displayLink對象就沒有加入任何的runloop菜枷,這樣回調(diào)也不會在每次刷新屏幕的時候執(zhí)行苍糠。

@property(getter=isPaused, nonatomic) BOOL paused;

paused可以用于暫停和開啟的設(shè)置。

@property(readonly, nonatomic) CFTimeInterval duration;

只讀的CFTimeInterval值啤誊,表示兩次屏幕刷新之間的時間間隔岳瞭。需要注意的是拥娄,該屬性在target的selector被首次調(diào)用以后才會被賦值。不過需要說明的一點(diǎn)是瞳筏,如果CPU過于繁忙稚瘾,duration的值是會浮動的。

@property(readonly, nonatomic) CFTimeInterval timestamp;

只讀的CFTimeInterval值姚炕,表示屏幕顯示的上一幀的時間戳摊欠,這個屬性通常被target用來計算下一幀中應(yīng)該顯示的內(nèi)容。需要注意的是柱宦,該屬性在target的selector被首次調(diào)用以后才會被賦值些椒。

@property(nonatomic) NSInteger frameInterval API_DEPRECATED("preferredFramesPerSecond", ios(3.1, 10.0), watchos(2.0,3.0), tvos(9.0,10.0));

事件觸發(fā)間隔,iOS10以后被廢棄掸刊,用preferredFramesPerSecond代替免糕。是指兩次selector觸發(fā)之間間隔幾次屏幕刷新,默認(rèn)值為1痒给,即每幀都調(diào)用一次selector说墨,這個也可以間接用來控制動畫速度。selector的調(diào)用間隔時間計算方式是:時間=duration×frameInterval苍柏。官方文檔中強(qiáng)調(diào)尼斧,當(dāng)該值被設(shè)定小于1時,結(jié)果是不可預(yù)知的试吁。

@property(nonatomic)NSInteger preferredFramesPerSecond ?API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));

iOS10以后的屬性棺棵,這個屬性說明了間隔多少幀調(diào)用一次回調(diào)。默認(rèn)是0熄捍,即每幀都調(diào)用回調(diào)烛恤,換句話說,就是一秒回調(diào)60次余耽。如果這個屬性值設(shè)為2缚柏,那么就是每兩幀回調(diào) 一次,也就是每秒回調(diào)30次碟贾。

實(shí)例代碼

#import "TestViewController.h"

@interface TestViewController ()

@property (nonatomic, strong) CADisplayLink *displayLink;

@end

@implementationTestViewController

- (void)viewDidLoad {

? ? [super viewDidLoad];

? ? self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(refreshEvent)];

? ? [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

? ? if(@available(iOS10.0, *)) {

? ? ? ? self.displayLink.preferredFramesPerSecond = 1;

? ? }else{

? ? ? ? self.displayLink.frameInterval=60;

? ? }

}

- (void)refreshEvent{

? ? NSLog(@"refreshEvent");

}

- (void)dealloc{

? ? NSLog(@"dealloc");

}

- (void)viewWillDisappear:(BOOL)animated{

? ? [super viewWillDisappear:animated];

? ? [self.displayLink invalidate];

? ? self.displayLink = nil;

}

@end

CADisplayLink優(yōu)勢:

依托于設(shè)備屏幕刷新頻率觸發(fā)事件币喧,所以其觸發(fā)時間上是最準(zhǔn)確的。也是最適合做UI不斷刷新的事件袱耽,過渡相對流暢杀餐,無卡頓感。

缺點(diǎn):

由于依托于屏幕刷新頻率朱巨,若果CPU不堪重負(fù)而影響了屏幕刷新史翘,那么觸發(fā)事件也會受到相應(yīng)影響。?

selector觸發(fā)的時間間隔只能是duration的整倍數(shù)。?

selector事件如果大于其觸發(fā)間隔就會造成掉幀現(xiàn)象琼讽。

另外?CADisplayLink?不能被繼承必峰。

CADisplayLink和NSTimer的不同

1.原理不同

CADisplayLink是一個能讓我們以和屏幕刷新率同步的頻率將特定的內(nèi)容畫到屏幕上的定時器類。?CADisplayLink以特定模式注冊到runloop后钻蹬,?每當(dāng)屏幕顯示內(nèi)容刷新結(jié)束的時候自点,runloop就會向?CADisplayLink指定的target發(fā)送一次指定的selector消息,?CADisplayLink類對應(yīng)的selector就會被調(diào)用一次脉让。

NSTimer以指定的模式注冊到runloop后,每當(dāng)設(shè)定的周期時間到達(dá)后功炮,runloop會向指定的target發(fā)送一次指定的selector消息溅潜。

2.周期設(shè)置方式不同

iOS10以前,CADisplayLink的selector?默認(rèn)調(diào)用周期是:時間=duration×frameInterval薪伏。iOS10以后滚澜,用preferredFramesPerSecond屬性代替,說明了間隔多少幀調(diào)用一次回調(diào)嫁怀。因此设捐,?CADisplayLink?周期的設(shè)置方式略顯不便。

NSTimer的selector調(diào)用周期可以在初始化時直接設(shè)定塘淑,相對就靈活的多萝招。

3、精確度不同

iOS設(shè)備的屏幕刷新頻率是固定的存捺,CADisplayLink在正常情況下會在每次刷新結(jié)束都被調(diào)用槐沼,精確度相當(dāng)高。

NSTimer的精確度就顯得低了點(diǎn)捌治,比如NSTimer的觸發(fā)時間到的時候岗钩,runloop如果在阻塞狀態(tài),觸發(fā)時間就會推遲到下一個runloop周期肖油。

4兼吓、使用場景

CADisplayLink使用場合相對專一,適合做UI的不停重繪森枪,比如自定義動畫引擎或者視頻播放的渲染视搏。

NSTimer的使用范圍要廣泛的多,各種需要單次或者循環(huán)定時處理的任務(wù)都可以使用疲恢。

后記:

CADisplayLink和NSTimer一樣凶朗,都要記得合適的時間invalidate,避免內(nèi)存泄漏显拳,這里采用了block的方法棚愤。

@class CADisplayLink;

typedefvoid(^executeDisplayLinkBlock) (CADisplayLink*displayLink);

@interfaceCADisplayLink (Block)

@property(nonatomic,copy)executeDisplayLinkBlock executeBlock;

+ (CADisplayLink*)displayLinkWithExecuteBlock:(executeDisplayLinkBlock)block;

@end

#import "CADisplayLink+Block.h"

#import?<objc/runtime.h>

@implementationCADisplayLink (Block)

- (void)setExecuteBlock:(executeDisplayLinkBlock)executeBlock {

? ? objc_setAssociatedObject(self, @selector(executeBlock), [executeBlock copy], OBJC_ASSOCIATION_COPY_NONATOMIC);

}

- (executeDisplayLinkBlock)executeBlock {

? ? return objc_getAssociatedObject(self, @selector(executeBlock));

}

+ (CADisplayLink*)displayLinkWithExecuteBlock:(executeDisplayLinkBlock)block{

? ? CADisplayLink*displayLink = [CADisplayLink displayLinkWithTarget:self?selector:@selector(executeDisplayLink:)];

? ? displayLink.executeBlock= [block copy];

? ? return?displayLink;

}

+ (void)executeDisplayLink:(CADisplayLink*)displayLink{

? ? if(displayLink.executeBlock) {

?? ? ? displayLink.executeBlock(displayLink);

? ? }

}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宛畦,更是在濱河造成了極大的恐慌瘸洛,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件次和,死亡現(xiàn)場離奇詭異反肋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)踏施,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門石蔗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人畅形,你說我怎么就攤上這事养距。” “怎么了日熬?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵棍厌,是天一觀的道長。 經(jīng)常有香客問我竖席,道長耘纱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任毕荐,我火速辦了婚禮束析,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘东跪。我一直安慰自己畸陡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布虽填。 她就那樣靜靜地躺著丁恭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斋日。 梳的紋絲不亂的頭發(fā)上牲览,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機(jī)與錄音恶守,去河邊找鬼第献。 笑死,一個胖子當(dāng)著我的面吹牛兔港,可吹牛的內(nèi)容都是我干的庸毫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼衫樊,長吁一口氣:“原來是場噩夢啊……” “哼飒赃!你這毒婦竟也來了利花?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤载佳,失蹤者是張志新(化名)和其女友劉穎炒事,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔫慧,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挠乳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了姑躲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睡扬。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖黍析,靈堂內(nèi)的尸體忽然破棺而出威蕉,到底是詐尸還是另有隱情,我是刑警寧澤橄仍,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站牍戚,受9級特大地震影響侮繁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜如孝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一宪哩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧第晰,春花似錦锁孟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至甜熔,卻和暖如春圆恤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腔稀。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工廉涕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贺氓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像廉白,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子采蚀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

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