码迷,mamicode.com
首页 > 移动开发 > 详细

iOS之 NSTimer

时间:2015-09-22 14:28:01      阅读:441      评论:0      收藏:0      [点我收藏+]

标签:

以前没怎么了解过这个NSTimer,其实还是有挺多坑的,今天来总结一下:

首先我们一起来看这个:

我在A  -> (push) -> B控制器,然后再B控制器中开启了一个NSTimer。然后我又pop到A

     技术分享

pop到A的时候,定时器还在运行,并且B没有被释放(未调用dealloc)。why?

这就不得不让我联想到我上篇写到的 “常驻线程”了,莫非NSTimer也是添加到了RunLoop?

     技术分享

这说明本例中的NSTimer确实是跑在了NSRunLoop中。

   技术分享

那为什么B没有释放呢?

  技术分享

Timer对Target进行了强引用。timer没有被释放,那么B就不会被释放了。也就走不到Dealloc了。那么我们就得在B离开的时候,要对timer进行invalidate。

- (void)viewWillDisappear:(BOOL)animated{
    
    [super viewWillDisappear:animated];
    [_timer invalidate];
}

 

 这个时候NSTimer 销毁了。pop到A的时候,有调用B的dealloc。

 

================ NSTimer 与 RunLoop 的关系

1.什么是NSTimer?

  A timer waits until a certain time interval has elapsed and then fires, sending a specified message to a target object.

  timer是一个能从某时刻或者周期性的给target对象发送一条指定的消息。

 

2. NSTimer的生命周期:

You specify whether a timer is repeating or non-repeating at creation time. A non-repeating timer fires once and then invalidates itself automatically, thereby preventing the timer from firing again. By contrast, a repeating timer fires and then reschedules itself on the same run loop.

A repeating timer always schedules itself based on the scheduled firing time, as opposed to the actual firing time

  NSTimer 会对外界传递的target进行retain。如果是一次性调用(repeats:NO),会在本次调用之后自身invalidate,并且NSTimer retain的那个target会做一次release。

  但是,如果是多次重复调用,就需要我们自己手动进行invalidate,不然NSTimer一直存在。

 

3. NSTimer的Tolerance(容差)

无论是单次执行的NSTimer还是重复执行的NSTimer都不是准时的,这与当前NSTimer所处的线程有很大的关系,如果NSTimer当前所处的线程正在进行大数据处理(假设为一个大循环),NSTimer本次执行会等到这个大数据处理完毕之后才会继续执行。
这期间有可能会错过很多次NSTimer的循环周期,但是NSTimer并不会将前面错过的执行次数在后面都执行一遍,而是继续执行后面的循环,也就是在一个循环周期内只会执行一次循环。
无论循环延迟的多离谱,循环间隔都不会发生变化,在进行完大数据处理之后,有可能会立即执行一次NSTimer循环,但是后面的循环间隔始终和第一次添加循环时的间隔相同。

4.Timers work in conjunction with run loops

其实上面的例子中我们使用的是“ create the timer and schedule it  on the current run loop in the default mode”。这个是在主线程中,所以Runloop是开启的,不需要我们手动打开。

         技术分享

 

  • 一个RunLoop包含若干个Mode,每个Mode又包含活干个Source/Timer/Oberver,每次调用RunLoop的主函数,只能指定其中的一个Mode, 这个Mode被称作CurrentMode。如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入。这样做的目的: 为了分隔不同组的Source/Timeer/Oberver,让其互不影响.
  • 在iOS多线程中,每一个线程都有一个Runloop,但是只有主线程的Runloop默认是打开的,其他子线程也就是我们创建的线程的Runloop默认是关闭的,需要我们手动运行。我们可以通过[NSRunLoop currentRunLoop]来获得当前线程的Runloop,并且调用[runloop addTimer:timer forMode:NSDefaultRunLoopMode]方法将定时器添加到runloop中,最后一定不要忘记调用runloop的run方法将当前runloop开启,否则NSTimer永远也不会运行。

 

 

 

 

 

 

iOS之 NSTimer

标签:

原文地址:http://www.cnblogs.com/Ohero/p/4828623.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!