iOS開發(fā),常常需要我們在某個時間刷新視圖,或者請求數(shù)據(jù)。這時,我們需要使用定時器。iOS中的定時方法很多,這里有三種比較常見的方法,沒有絕對的優(yōu)劣性,只是不同的應(yīng)用場景,使用不同的方法。
一、NSTimer
1.特點
我們可以指定一個時間,讓timer一次性的或者周期性的觸發(fā)一個自定義的方法。但是timer有個需要注意的地方。timer可能會存在延時,不管是一次性的還是周期性的timer,都會與RunLoop和RunLoop Mode有關(guān),如果這個RunLoop正在執(zhí)行一個連續(xù)性的運算,timer就會延時出發(fā)。重復(fù)性的timer遇到這種情況,如果延遲超過了一個周期,則會在延時結(jié)束后立刻執(zhí)行,并按照之前指定的周期繼續(xù)執(zhí)行。
2.NSTimer的創(chuàng)建方法
(1)自動加入RunLoop的創(chuàng)建方法
/**
* 方法一
**/
NSTimer *times1=[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
//可以直接在代碼塊中編寫你要執(zhí)行的代碼
}];
/**
* 方法二:@selector()中寫你要執(zhí)行的方法
**/
NSTimer *time2=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(run:) userInfo:nil repeats:YES];
注意:如果repeats為Yes,我們還需要在執(zhí)行完畢的時候,手動的銷毀,否者會造成內(nèi)存泄漏,如下:
//手動釋放timer的方法
[timer invalidate];
(2)需要手動加入RunLoop的創(chuàng)建方法
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(run:) userInfo:nil repeats:YES];
//手寫代碼,加入runLoop
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
二、CADisplayLink
1.特點
該方法會在屏幕刷新時被調(diào)用,CADisplayLink是一個能讓調(diào)用頻率與屏幕的刷新率同步的定時器類。CADisplayLink是以特定模式注冊到runloop后,每當(dāng)屏幕顯示內(nèi)容刷新結(jié)束的時候(通常iOS設(shè)備屏幕的刷新率60次/秒),runloop就會向CADisplayLink指定的target發(fā)送一次指定的selector消息, 也就是說,CADisplayLink類對應(yīng)的selector就會被調(diào)用一次。
但是,這個刷新方法同樣有可能遇到延時的情況,比如:iOS設(shè)備的屏幕刷新頻率是固定的,CADisplayLink在正常情況下會在每次刷新結(jié)束都被調(diào)用,精確度相當(dāng)高。但如果調(diào)用的方法比較耗時,超過了屏幕的刷新周期,就會導(dǎo)致跳過若干次回調(diào)調(diào)用的機會。還有一種情況是CPU過于繁忙,無法保證屏幕60次/秒的刷新頻率,就會導(dǎo)致跳過若干次調(diào)用回調(diào)方法的機會,跳過次數(shù)完全取決于CPU的忙碌程度。
從原理上可以看出,CADisplayLink適合做界面的重繪。
2.CADisplayLink的創(chuàng)建方法
CADisplayLink *displayLink=[CADisplayLink displayLinkWithTarget:self selector:@selector(run:)];
//frameInterval屬性是用來設(shè)置方法的調(diào)用間隔的,有時候我們并不需要這么快的調(diào)用頻率。
//我們就可以自己定義多少幀調(diào)用一次,frameInterval的默認(rèn)值是1,如果是5,相當(dāng)于每秒調(diào)用12次(60/5)。
displayLink.frameInterval=5;
//執(zhí)行了下面一行代碼,相當(dāng)于定時器啟動了,selector就能被周期性調(diào)用,如果想要停止,往下看!
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
定時器停止的方法
[displayLink invalidate];
displayLink = nil;
如何計算方法調(diào)用的時間間隔吶?
CADisplayLink中有個duration屬性,該屬性在target的selector被首次調(diào)用以后才會被賦值。selector的調(diào)用間隔時間計算方式是:調(diào)用間隔時間 = duration × frameInterval。
注意,duration只能讀,不能寫!
三、GCD
1.特點
GCD很強大,這里只寫其中的兩個用法,如果要想詳細(xì)的了解GCD。
傳送門:(叮咚!) GCD詳解 <-點這里
2.GCD用法
第一種:執(zhí)行一次
創(chuàng)建的方法:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//執(zhí)行事件
});
第二種:重復(fù)執(zhí)行
創(chuàng)建的方法:
NSTimeInterval period = 1.0; //設(shè)置時間間隔
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //如果period==1,就是每秒執(zhí)行
dispatch_source_set_event_handler(_timer, ^{
//在這里執(zhí)行事件
});
暫停定時器的方法如下,在需要的地方調(diào)用即可:
dispatch_resume(_timer);
【有什么沒寫清楚的,下方留言!】