iOS 定時器 NSTimer、CADisplayLink、GCD3種方式的實現

在軟件開發過程當中,咱們經常須要在某個時間後執行某個方法,或者是按照某個週期一直執行某個方法。在這個時候,咱們就須要用到定時器。html

然而,在iOS中有不少方法完成以上的任務,到底有多少種方法呢?通過查閱資料,大概有三種方法:NSTimer、CADisplayLink、GCD。接下來我就一一介紹它們的用法。ios

1、NSTimeroop

1. 建立方法學習

1 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action:) userInfo:nil repeats:NO];
  • TimerInterval : 執行以前等待的時間。好比設置成1.0,就表明1秒後執行方法ui

  • target : 須要執行方法的對象。atom

  • selector : 須要執行的方法spa

  • repeats : 是否須要循環線程

2. 釋放方法code

1 [timer invalidate];
  • 注意 :視頻

調用建立方法後,target對象的計數器會加1,直到執行完畢,自動減1。若是是循環執行的話,就必須手動關閉,不然能夠不執行釋放方法。

3. 特性

  • 存在延遲

無論是一次性的仍是週期性的timer的實際觸發事件的時間,都會與所加入的RunLoop和RunLoop Mode有關,若是此RunLoop正在執行一個連續性的運算,timer就會被延時出發。重複性的timer遇到這種狀況,若是延遲超過了一個週期,則會在延時結束後馬上執行,並按照以前指定的週期繼續執行。

  • 必須加入Runloop

使用上面的建立方式,會自動把timer加入MainRunloop的NSDefaultRunLoopMode中。若是使用如下方式建立定時器,就必須手動加入Runloop:

1 NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
2 [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

 

UIScrollView 拖動時執行的是 UITrackingRunLoopMode,會致使暫停定時器,等恢復爲 NSDefaultRunLoopMode 時才恢復定時器。

因此若是須要定時器在 UIScrollView 拖動時也不影響的話,建議添加到 UITrackingRunLoopMode 或 NSRunLoopCommonModes 中:

1 NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
2 [[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode]; ///< 或者 NSRunLoopCommonModes

2、CADisplayLink

1. 建立方法

1 self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];    
2 [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

2. 中止方法

1 [self.displayLink invalidate];  
2 self.displayLink = nil;
3         
4 /**當把CADisplayLink對象add到runloop中後,selector就能被週期性調用,相似於重複的NSTimer被啓動了;執行invalidate操做時,CADisplayLink對象就會從runloop中移除,selector調用也隨即中止,相似於NSTimer的invalidate方法。**/

3. 特性

  • 屏幕刷新時調用

    CADisplayLink是一個能讓咱們以和屏幕刷新率同步的頻率將特定的內容畫到屏幕上的定時器類。CADisplayLink以特定模式註冊到runloop後,每當屏幕顯示內容刷新結束的時候,runloop就會向CADisplayLink指定的target發送一次指定的selector消息, CADisplayLink類對應的selector就會被調用一次。因此一般狀況下,按照iOS設備屏幕的刷新率60次/秒

  • 延遲

    • iOS設備的屏幕刷新頻率是固定的,CADisplayLink在正常狀況下會在每次刷新結束都被調用,精確度至關高。但若是調用的方法比較耗時,超過了屏幕刷新週期,就會致使跳過若干次回調調用機會。

    • 若是CPU過於繁忙,沒法保證屏幕60次/秒的刷新率,就會致使跳過若干次調用回調方法的機會,跳過次數取決CPU的忙碌程度。

  • 使用場景

    從原理上能夠看出,CADisplayLink適合作界面的不停重繪,好比視頻播放的時候須要不停地獲取下一幀用於界面渲染。

4. 重要屬性

  • frameInterval

    NSInteger類型的值,用來設置間隔多少幀調用一次selector方法,默認值是1,即每幀都調用一次。

  • duration

    readOnly的CFTimeInterval值,表示兩次屏幕刷新之間的時間間隔。須要注意的是,該屬性在target的selector被首次調用之後纔會被賦值。selector的調用間隔時間計算方式是:調用間隔時間 = duration × frameInterval。

 

3、GCD方式

  • 執行一次

  • 1 double delayInSeconds = 2.0;
    2 dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
    3 dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    4     //執行事件
    5 });
  • 重複執行

  • 複製代碼
    1 NSTimeInterval period = 1.0; //設置時間間隔
    2 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    3 dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    4 dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每秒執行
    5 dispatch_source_set_event_handler(_timer, ^{
    6      //在這裏執行事件
    7 });
    8 dispatch_resume(_timer);

    複製代碼

  1.建立方法

//須要將dispatch_source_t timer設置爲成員變量,否則會當即釋放
@property (nonatomic, strong) dispatch_source_t timer;
//定時器開始執行的延時時間
NSTimeInterval delayTime = 3.0f;
//定時器間隔時間
NSTimeInterval timeInterval = 3.0f;  
//建立子線程隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//使用以前建立的隊列來建立計時器
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//設置延時執行時間,delayTime爲要延時的秒數
dispatch_time_t startDelayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC));
//設置計時器
dispatch_source_set_timer(_timer, startDelayTime, timeInterval * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(_timer, ^{     
  //執行事件
 });
// 啓動計時器
dispatch_resume(_timer)

  

  2.中止方法

dispatch_source_cancel(_timer);

  

  3.重要屬性

 

收藏學習,轉自:

iOS中幾種定時器 - 控制了時間,就控制了一切

iOS中的定時器

相關文章
相關標籤/搜索