iOS開發(fā) 定時器方法---NSTimer、CADisplayLink、GCD

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);

【有什么沒寫清楚的,下方留言!】

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容