iOS NSTimer不走的问题

时间:2022-07-23
本文章向大家介绍iOS NSTimer不走的问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

iOS NSTimer不走的问题

背景

这个版本上线后,突然发现埋点数据直线下降,调试后发现是定时器上传的方法没有走,但是定时器的方法本期并没有修改过。代码如下

- (BOOL)initTimer() {
        self.uploadTimer = [NSTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(handleUpload) userInfo:nil repeats:YES];
		[[NSRunLoop currentRunLoop] addTimer:self.uploadTimer forMode:NSRunLoopCommonModes];
}

排查

这个handleUpload方法,怎么都不会走,但是在之前的版本中就是好的,排查了之后发现,是外层调用的地方加了一层异步。即调用的地方变成了

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    initTimer()
});

然后就导致了定时器没有启动。

原因

iOS是通过runloop作为消息循环机制,主线程默认启动了runloop,可是自线程没有默认的runloop,因此,我们在子线程启动定时器是不生效的。

解决方法:在子线程启动一下runloop即可

- (BOOL)initTimer() {
        self.uploadTimer = [NSTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(handleUpload) userInfo:nil repeats:YES];
		[[NSRunLoop currentRunLoop] addTimer:self.uploadTimer forMode:NSRunLoopCommonModes];
        [[NSRunLoop currentRunLoop] run];
}

思考

通过这个问题,有两点收获,

  1. timer在iOS开发中经常使用,在很多博客中都看到关于timer要注意的地方也很多,通常是内存管理,timer启动相关,但是在开发中,如果没有真正遇到问题,没有“疼”在自己身上,就自己注意的就不够,经过这次之后,相信以后再要在异步使用timer,肯定会留心很多。
  2. 这个地方initTimer其实是一个SDK初始化的类,其实SDK内部没有修改,但是外层使用SDK的App调用修改了,就导致了SDK不能正常工作。所以封装SDK时要注意,如果使用timer,要么做线程检查,要么就直接把代码安全保证好;因为不能保证第三方调用者使用时的情况,所以要保证自己代码的正确性。

参考

IOS定时器操作和NSTimer的各种坑