美文网首页
iOS / NSTimer

iOS / NSTimer

作者: 不不不不同学 | 来源:发表于2020-03-09 00:11 被阅读0次

    1、创建

    (1.1)timerWithTimeInterval 创建

    在调用 fire 方法后唤醒开始运行。

    self.timer = [NSTimer timerWithTimeInterval:2 repeats:true block:^(NSTimer * _Nonnull timer) 
        NSLog(@"timer");
    }];
    [self.timer fire];
    

    (1.2)scheduledTimerWithTimeInterval 创建

    创建后立刻唤醒开始运行。

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(method) userInfo:nil repeats:YES];
    

    2、控制

    (2.1)暂停

    原理:触发时间设置在未来

    [self.timer setFireDate:[NSDate distantFuture]];
    

    (2.2)继续 / 开始

    原理:触发时间设置在现在

    [self.timer setFireDate:[NSDate date]];
    

    (2.3)停止

    原理:停止定时器

    [self.timer invalidate];
    

    3、关于 Runloop 切换场景

    (3.1)关于被 Runloop 持有

    NSTimer 会被添加在所在线程的 Runloop 中,而 Runloop 对 Timer 是一种强持有关系。为什么呢?
    (1)RunLoop 有一个基于时间的触发器的类,CFRunLoopTimerRef,和 NSTimer 是 toll-free bridged 的桥接对应关系。
    (2)CFRunLoopTimerRef 包含 时间长度、回调(函数指针)
    (3)当 NSTimer 加入到 RunLoop 时,RunLoop 会注册对应的时间点,当时间点到达时,RunLoop 会被唤醒,以执行那个回调。

    (3.2)关于默认运行 Mode

    NSTimer 默认是被加入到了 kCFRunLoopDefaultMode
    所以当 Runloop 的 Mode 变化时,当前的 NSTimer 就不会工作了。

    场景:
    当滑动 TableView 时,RunLoop 切换到 UITrackingRunLoopMode。
    而 NSTimer 是在 kCFRunLoopDefaultMode下的,就无法接受处理 Timer 的事件。此时 Timer 的事件将不会被触发调用。

    如何解决:
    (1)将 Timer 添加到 UITrackingRunLoopMode —— 不行,因默认情况下则不运行。
    (2)将 Timer 同时添加到 UITrackingRunLoopMode 和 kCFRunLoopDefaultMode 上 —— 默认情况、滑动ScrollerView时,均能运行。

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(method) userInfo:nil repeats:YES];
    
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    

    Timer 则被添加到多个mode上。
    (3)使用 GCD 定时器。

    4、关于其他定时器

    相关文章

      网友评论

          本文标题:iOS / NSTimer

          本文链接:https://www.haomeiwen.com/subject/zaxrbctx.html