iOS定時(shí)器的添加方式及其與runloop的關(guān)系

定時(shí)器是iOS開(kāi)發(fā)中頻繁使用的開(kāi)發(fā)技能,存在多種創(chuàng)建方式,可根據(jù)實(shí)際需求選用;
iOS中的定時(shí)器大致分為這幾類:

  • NSTimer
  • CADisplayLink
  • GCD定時(shí)器

NSTimer

NSTimer是最常用的定時(shí)器創(chuàng)建方式,比較常用的創(chuàng)建方法有以下兩種:

+ (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;

兩種方法創(chuàng)建的定時(shí)器區(qū)別在于以下點(diǎn):

  1. scheduledTimerWithTimeInterval 在主線程創(chuàng)建的定時(shí)器會(huì)在創(chuàng)建后自動(dòng)將 timer
    添加到主線程的 runloop 并啟動(dòng),主線程的 runloopMode 為 NSDefaultRunLoopMode,但是在 ScrollView 滑動(dòng)時(shí)執(zhí)行的是 UITrackingRunLoopModeNSDefaultRunLoopMode被掛起,定時(shí)器失效,等到停止滑動(dòng)才恢復(fù);
    因此需要將 timer 分別加入 UITrackingRunLoopModeNSDefaultRunLoopMode 中:
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode];

或者直接添加到 NSRunLoopCommonModes 中:

[[NSRunLoop mainRunLoop] addTimer:timer forMode: NSRunLoopCommonModes];

也可新開(kāi)一個(gè)子線程,主線程的 runloop 是自動(dòng)開(kāi)啟的,但子線程的 runloop 需要手動(dòng)開(kāi)啟,代碼如下:

    __block NSInteger count = 0;
    [NSThread detachNewThreadWithBlock:^{
        _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            count++;
            NSLog(@"第%li次", count);
        }];
        [[NSRunLoop currentRunLoop] run];
    }];
如果用 timerWithTimeInterval 創(chuàng)建則需要手動(dòng)添加到 runloop 中;
  1. timerWithTimeInterval 創(chuàng)建的定時(shí)器不會(huì)直接啟動(dòng),而需要手動(dòng)添加到 runloop 中;為防止出現(xiàn)滑動(dòng)視圖時(shí)定時(shí)器被掛起,可直接添加到 NSRunLoopCommonModes;

CADisplayLink

什么是 CADisplayLink

CADisplaylink 是一個(gè)計(jì)時(shí)器對(duì)象,可以使用這個(gè)對(duì)象來(lái)保持應(yīng)用中的繪制與顯示刷新的同步。更通俗的講,電子顯示屏都是由一個(gè)個(gè)像素點(diǎn)構(gòu)成,要讓屏幕顯示的內(nèi)容變化,需要以一定的頻率刷新這些像素點(diǎn)的顏色值,系統(tǒng)會(huì)在每次刷新時(shí)觸發(fā) CADisplaylink。

CADisplayLink的使用

// CADisplayLink
- (void)sa_displayLink {
    _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkAction)];
    [_displayLink setFrameInterval:50];   //設(shè)置 CADisplayLink selector 調(diào)用時(shí)間間隔
    [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; 添加到 runloop,并指定 RunloopMode;
}
// CADisplayLink selector 調(diào)用
- (void)displayLinkAction {
    static NSInteger count = 0;
    count++;
    NSLog(@"第%li次調(diào)用", count);
}

下面是 setFrameInterval 分別設(shè)置 5 和 50的打印結(jié)果,可看出selector調(diào)用時(shí)間間隔不同:

setFrameInterval:50.png

setFrameInterval:5.png

調(diào)用setPaused:可以暫停、開(kāi)啟 CADisplayLink;

[_displayLink setPaused:YES];

停止使用 CADisplayLink,調(diào)用 invalidate
有些需求配合使用 CADisplayLink 可以更簡(jiǎn)便實(shí)現(xiàn);

GCD定時(shí)器

直接貼一個(gè)demo方法看看使用:

- (void)gcdTimerDemoMethod {
    __block int count = 0;
    __block dispatch_source_t gcdTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());      //創(chuàng)建定時(shí)器,并指定線程,dispatch_source_t 本質(zhì)上也是一個(gè)OC對(duì)象;
    
    dispatch_source_set_timer(gcdTimer, DISPATCH_TIME_NOW, (uint64_t)(1.0 * NSEC_PER_SEC), 0);   //設(shè)置定時(shí)器間隔時(shí)間
    
    //設(shè)置定時(shí)器 action
    dispatch_source_set_event_handler(gcdTimer, ^{
        NSLog(@"------------%@", [NSThread currentThread]);
        count++;
        if (count == 4) {
            // 取消定時(shí)器
            dispatch_cancel(gcdTimer);
            gcdTimer = nil;
        }
    });
    dispatch_resume(gcdTimer);  //啟動(dòng)定時(shí)器
}

//定時(shí)器釋放
- (void)dealloc {
    dispatch_source_cancel(_timer);
    dispatch_cancel(_timer);
    _timer = nil;
}

GCD 定時(shí)器比 NSTimer 更精確,定時(shí)器一定要被強(qiáng)引用,不然會(huì)被釋放,導(dǎo)致的定時(shí)器無(wú)效;

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

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

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