【iOS沉思录】如何创建NSTimer并使其在当前线程中正常运行?

NSTimer主要用于开启定时任务,但要真确使用才能保证其正常有效运行。尤其要注意以下两点:

  • 确保NSTimer已经添加到当前RunLoop;
  • 确保当前RunLoop已经启动。

1.创建NSTimer有两种方法:

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

这两种方法的主要区别为,使用timerWithTimeInterval创建的timer不会自动添加到当前RunLoop中,需要手动添加并制定RunLoop的模式:[[NSRunLoop currentRunLoop] addTimer:mainThreadTimer forMode:NSDefaultRunLoopMode]; 而使用scheduledTimerWithTimeInterval创建的RunLoop会默认自动添加到当前RunLoop中。

2.NSTimer可能在主线程中创建,也可能在子线程中创建:

主线程中的RunLoop默认是启动的,所以timer只要添加到主线程RunLoop中就会被执行;而子线程中的RunLoop默认是不启动的,所以timer添加到子线程RunLoop中后,还要手动启动RunLoop才能使timer被执行。

NSTimer只有添加到启动起来的RunLoop中才会正常运行。NSTimer通常不建议添加到主线程中执行,因为界面的更新在主线程中,界面导致的卡顿会影响NSTimer的准确性。

以下为四种情形下正确的使用方法:

- (void)viewDidLoad {
    [super viewDidLoad];
    /* 主线程中创建timer */
    NSTimer *mainThreadTimer = [NSTimer timerWithTimeInterval:10.0 target:self selector:@selector(mainThreadTimer_SEL) userInfo:nil repeats:YES];
    NSTimer *mainThreadSchduledTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(mainThreadSchduledTimer_SEL) userInfo:nil repeats:YES];
    /* 将mainThreadTimer1添加到主线程runloop */
    [[NSRunLoop currentRunLoop] addTimer:mainThreadTimer forMode:NSDefaultRunLoopMode];

    /* 子线程中创建timer */
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSTimer *subThreadTimer = [NSTimer timerWithTimeInterval:10.0 target:self selector:@selector(subThreadTimer_SEL) userInfo:nil repeats:YES];
        NSTimer *subThreadSchduledTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(subThreadSchduledTimer_SEL) userInfo:nil repeats:YES];
        /* 将subThreadTimer1添加到子线程runloop */
        [[NSRunLoop currentRunLoop] addTimer:subThreadTimer forMode:NSDefaultRunLoopMode];
        /* 启动子线程runloop */
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    });
}

- (void) mainThreadTimer_SEL{
    NSLog(@"mainThreadTimer is working!");
}
- (void) mainThreadSchduledTimer_SEL{
    NSLog(@"mainThreadSchduledTimer is working!");
}

- (void) subThreadTimer_SEL{
    NSLog(@"subThreadTimer is working!");
}
- (void) subThreadSchduledTimer_SEL{
    NSLog(@"subThreadSchduledTimer is working!");
}

打印结果为:

2018-01-31 20:24:10.729259+0800 IOSDemo[41891:4382661] mainThreadSchduledTimer is working!
2018-01-31 20:24:20.728351+0800 IOSDemo[41891:4382661] mainThreadTimer is working!
2018-01-31 20:24:20.728409+0800 IOSDemo[41891:4382720] subThreadTimer is working!
2018-01-31 20:24:20.728693+0800 IOSDemo[41891:4382720] subThreadSchduledTimer is working!

NSTimer的释放方法:

[timer invalidate];

猜你喜欢

转载自blog.csdn.net/cordova/article/details/79225004