代码改变世界

NSTimer

2018-05-01 16:29  dengchaojie_learner  阅读(181)  评论(0编辑  收藏  举报

A repeating timer reschedules itself based on the scheduled firing time, not the actual firing time. For example, if a timer is scheduled to fire at a particular time and every 5 seconds after that, the scheduled firing time will always fall on the original 5 second time intervals, even if the actual firing time gets delayed. If the firing time is delayed so far that it passes one or more of the scheduled firing times, the timer is fired only once for that time period; the timer is then rescheduled, after firing, for the next scheduled firing time in the future.

综上: timer都会对它的target进行retain,我们需要小心对待这个target的生命周期问题,尤其是重复性的timer。

重复性的timer遇到这种情况,如果延迟超过了一个周期,则会和后面的触发进行合并,即在一个周期内只会触发一次。但是不管该timer的触发时间延迟的有多离谱,他后面的timer的触发时间总是倍数于第一次添加timer的间隙。

timer并不会因为触发延迟而导致后面的触发时间发生延迟。

综上: timer不是一种实时的机制,会存在延迟,而且延迟的程度跟当前线程的执行情况有关。

综上: 必须得把timer添加到runloop中,它才会生效。

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    // 打开下面一行输出runloop的内容就可以看出,timer却是已经被添加进去
    //NSLog(@"the thread's runloop: %@", [NSRunLoop currentRunLoop]);
    
    // 打开下面一行, 该线程的runloop就会运行起来,timer才会起作用
    //[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];

综上: 要让timer生效,必须保证该线程的runloop已启动,而且其运行的runloopmode也要匹配。


timer执行是否准时

不准时!

第一种不准时:有可能跳过去

  1. 线程处理比耗时的事情时会发生
  2. 还有就是timer添加到的runloop模式不是runloop当前运行的模式,这种情况经常发生。

 

对于第一种情况我们不应该在timer上下功夫,而是应该避免这个耗时的工作。那么第二种情况,作为开发者这也是最应该去关注的地方,要留意,然后视情况而定是否将timer添加到runloop多个模式

虽然跳过去,但是,接下来的执行不会依据被延迟的时间加上间隔时间,而是根据之前的时间来执行。比如:

定时时间间隔为2秒,t1秒添加成功,那么会在t2、t4、t6、t8、t10秒注册好事件,并在这些时间触发。假设第3秒时,执行了一个超时操作耗费了5.5秒,则触发时间是:t2、t8.5、t10,第4和第6秒就被跳过去了,虽然在t8.5秒触发了一次,但是下一次触发时间是t10,而不是t10.5。

第二种不准时:不准点

比如上面说的t2、t4、t6、t8、t10,并不会在准确的时间触发,而是会延迟个很小的时间,原因也可以归结为2点:

    1. RunLoop为了节省资源,并不会在非常准确的时间点触发
    2. 线程有耗时操作,或者其它线程有耗时操作也会影响

https://www.cnblogs.com/mddblog/p/6517377.html
http://www.cnblogs.com/smileEvday/archive/2012/12/21/NSTimer.html