在開(kāi)發(fā)中,有時(shí)候,我們會(huì)用到定時(shí)器,像獲取驗(yàn)證碼倒計(jì)時(shí),語(yǔ)音播放倒計(jì)時(shí),又或者循環(huán)展示某一個(gè)廣告之類(lèi)的等等,都會(huì)用到計(jì)時(shí)器,在iOS中,常用的定時(shí)器有兩種GCD,NSTimer,還有一種不常用的CADisplayLink,都在此總結(jié)一下,實(shí)際開(kāi)發(fā)中,還是選擇自己熟悉的定時(shí)器.
文章首發(fā)于一之筆,轉(zhuǎn)載參考,注明來(lái)源OC中的定時(shí)器;
定時(shí)器之---NSTimer
NSTimer常用的兩種創(chuàng)建方法
/**
* 創(chuàng)建定時(shí)器
* @param ti 定時(shí)器間隔時(shí)間
* @param aTarget 監(jiān)聽(tīng)對(duì)象(一般為self)
* @param aSelector 定時(shí)器執(zhí)行方法
* @param userInfo 定時(shí)器傳遞的信息,可傳nil
* @param yesOrNo 是否重復(fù)
*/
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
第一種方法
通過(guò)timerWith...創(chuàng)建的定時(shí)器,必須注意,需要將定時(shí)器手動(dòng)添加到當(dāng)前的runloop中,否則定時(shí)器不會(huì)激發(fā),并且要注意runloop的模式,關(guān)于runloop的模式,主要有NSDefaultRunLoopMode
和UITrackingRunLoopMode
,而這兩種模式都被稱(chēng)為[通用模式]NSRunLoopCommonModes
,可以通過(guò)NSLog打印當(dāng)前模式,[NSRunloop currentRunloop],runloop的設(shè)定模式不同,定時(shí)器的作用就不同,具體如下:
//創(chuàng)建定時(shí)器
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
//添加帶runloop中,并且設(shè)定模式(默認(rèn)模式,當(dāng)用戶(hù)進(jìn)行交互的時(shí)候,定時(shí)器會(huì)停止工作)
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
或者(追蹤模式,通俗的說(shuō),就是當(dāng)用戶(hù)進(jìn)行交互的時(shí)候,定時(shí)器不受影響)
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
或者(通用模式)
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
//當(dāng)前runloop的打印結(jié)果
/* NSRunLoopCommonModes:如果設(shè)置 Runloop 的模式為 Common 則被標(biāo)記為 common 的模式,定時(shí)器都可以運(yùn)行,而forMode:NSDefaultRunLoopMode和forMode:UITrackingRunLoopMode都被標(biāo)記為 common
common modes = <CFBasicHash 0x7f886b402720 [0x10bad07b0]>{type = mutable set, count = 2, entries =>
0 : <CFString 0x10c95ba40 [0x10bad07b0]>{contents = "UITrackingRunLoopMode"}
2 : <CFString 0x10baf0b40 [0x10bad07b0]>{contents = "kCFRunLoopDefaultMode"} } */
第二種方法
通過(guò)scheduled...創(chuàng)建的定時(shí)器,系統(tǒng)會(huì)默認(rèn)將定時(shí)器添加到默認(rèn)的模式中,但是我們可以人為的修改定時(shí)器的運(yùn)行模
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
//更改模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
定時(shí)器之---GCD
和NSTimer相比,GCD中的定時(shí)器,不受runloop模式的影響,使用起來(lái),也比較方便,直接敲dispatch_source會(huì)有代碼段提示,然后就是補(bǔ)充參數(shù)即可,但是需要注意:由于GCD創(chuàng)建的定時(shí)器會(huì)在block中有回調(diào),所以一開(kāi)始創(chuàng)建的定時(shí)器要被強(qiáng)引用
,否則,一旦創(chuàng)建完,當(dāng)回調(diào)block的時(shí)候,早都掛了,具體如下:
- (void)gcdTimer
{
//0 獲取一個(gè)全局的并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//1. 定義一個(gè)定時(shí)器
/**
第一個(gè)參數(shù):說(shuō)明定時(shí)器的類(lèi)型
第四個(gè)參數(shù):GCD的回調(diào)任務(wù)添加到那個(gè)隊(duì)列中執(zhí)行蚁吝,如果是主隊(duì)列則在主線(xiàn)程執(zhí)行 */
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//這里創(chuàng)建的 timer, 是一個(gè)局部變量,由于 Block 回調(diào)定時(shí)器,因此,必須保證 timer 被強(qiáng)引用; self.timer = timer;
dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0 * NSEC_PER_SEC); /** *
<#dispatch_source_t source#>:給哪個(gè)定時(shí)器設(shè)置時(shí)間
<#dispatch_time_t start#>:定時(shí)器立即啟動(dòng)的開(kāi)始時(shí)間
<#uint64_t interval#>:定時(shí)器開(kāi)始之后的間隔時(shí)間
<#uint64_t leeway#>:定時(shí)器間隔時(shí)間的精準(zhǔn)度,傳入0代表最精準(zhǔn),盡量讓定時(shí)器精準(zhǔn),注意: dispatch 的定時(shí)器接收的時(shí)間是 納秒
*/
uint64_t interval = 2.0 * NSEC_PER_SEC;
//2設(shè)置定時(shí)器的相關(guān)參數(shù):開(kāi)始時(shí)間,間隔時(shí)間,精準(zhǔn)度等
dispatch_source_set_timer( timer, startTime, interval, 0 * NSEC_PER_SEC);
//3.設(shè)置定時(shí)器的回調(diào)方法
dispatch_source_set_event_handler(timer, ^{
NSLog(@"%@",[NSThread currentThread]);
});
//4.開(kāi)啟定時(shí)器
dispatch_resume(timer);
}
定時(shí)器之---CADisplayLink
CADisplayLink是什么?
一個(gè)能讓我們保證和屏幕刷新率同步的頻率(通常情況下,iOS設(shè)備屏幕的刷新率60次/秒),將特定的內(nèi)容畫(huà)到屏幕上的定時(shí)器類(lèi),而不會(huì)想NSTimer出現(xiàn)屏幕卡頓現(xiàn)象。
這個(gè)定時(shí)器一般不常用,這個(gè)主要用在快速刷新屏幕時(shí),簡(jiǎn)單了解一下他的用法,這里還需要了解一下這個(gè)方法:setNeedsDisplay(重繪),系統(tǒng)底層會(huì)調(diào)用:- (void)drawRect:(CGRect)rect
;需要注意的是:這個(gè)方法不是立馬就進(jìn)行重繪.它僅僅是設(shè)置了一個(gè)重繪標(biāo)志,等到下一次屏幕刷新的時(shí)候才會(huì)調(diào)用DrawRect方法.
CADisplayLink以特定模式添加到runloop后舀射,每當(dāng)屏幕顯示內(nèi)容刷新結(jié)束的時(shí)候窘茁,runloop就會(huì)向CADisplayLink指定的target發(fā)送一次指定的selector消息, CADisplayLink類(lèi)對(duì)應(yīng)的selector就會(huì)被調(diào)用一次脆烟。
具體使用如下:
如何使用?
-(void)viewDidLoad
{ CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
//重繪的方法
//初始化frame
static int _mdsY = 0;
- (void)drawRect:(CGRect)rect
{
//對(duì)需要繪制的對(duì)象進(jìn)行修改
if(_mdsY > rect.size.height){
_mdsY = 0;
}
UIImage *image = [UIImage imageNamed:@"MandarinTalk"];
[image drawAtPoint:CGPointMake(0, _mdsY)];
_mdsY += 10;
}
總的來(lái)說(shuō),OC中的定時(shí)器,就這么多,最常用的也就是前兩種,但是具體使用哪種定時(shí)器,看個(gè)人自己了,有什么問(wèn)題,非常歡迎!謝謝.