iOS / NSTimer

2020-03-09  本文已影响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、关于其他定时器

上一篇下一篇

猜你喜欢

热点阅读