以前没怎么了解过这个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对象发送一条指定的消息。

  定时器是线程通知自己做某件事的方法,定时器和你的RunLoop的特定的模式相关。如果定时器所在的模式当前未被RunLoop监视,那么定时器将不会开始 直到RunLoop运行在相应的模式下。如果RunLoop不在运行,那定时器也将永远不启动。

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一直存在。

  invalidate的方法中有这么一段话:

You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.

  NSTimer在那个线程创建就要在那个线程停止,否则资源不能正确的释放。

3. NSTimer的Tolerance(容差),不是实时机制

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

  重复工作定时器会基于安排好的时 间而非实际时间调度它自己运行。举个例子,如果定时器被设定在某一特定时间开始 并 5 秒重复一次,那么定时器会在那个特定时间后 5 秒启动,即使在那个特定的触发 时间延迟了。如果定时器被延迟以至于它错过了一个或多个触发时间,那么定时器会 在下一个最近的触发事件启动,而后面会按照触发间隔正常执行

4.Timers work in conjunction with run loops

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

  • 上面的Source/Timer/Observer被统称为mode item,一个item可以被同时加入多个mode。但一个item被重复加入同一个mode时是不会有效果的。如果一个mode中一个item都没有,则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永远也不会运行。

NSTimer可以创建一个定时源。

 NSRunLoop *myRunLoop = [NSRunLoop currentRunLoop];
NSDate *futureDate = [NSDate dateWithTimeIntervalSinceNow:1.0];
_timer = [[NSTimer alloc] initWithFireDate:futureDate interval: target:self selector:@selector(doSomething) userInfo:nil repeats:YES]; [myRunLoop addTimer:_timer forMode:NSDefaultRunLoopMode];

5.对于UIScrollView的Timer

当使用NSTimerscheduledTimerWithTimeInterval方法时。事实上此时Timer会被加入到当前线程的Run Loop中,且模式是默认的NSDefaultRunLoopMode。而如果当前线程就是主线程,也就是UI线程时,某些UI事件,比如UIScrollView的拖动操作,会将Run Loop切换成NSEventTrackingRunLoopMode模式,在这个过程中,默认的NSDefaultRunLoopMode模式中注册的事件是不会被执行的。也就是说,此时使用scheduledTimerWithTimeInterval添加到RunLoop中的Timer就不会执行。

 NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES];
//使用NSRunLoopCommonModes模式,把timer加入到当前Run Loop中。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

iOS之 NSTimer(一)的更多相关文章

  1. iOS定时器-- NSTimer 和CADisplaylink

    iOS定时器-- NSTimer 和CADisplaylink 一.iOS中有两种不同的定时器: 1.  NSTimer(时间间隔可以任意设定,最小0.1ms)// If seconds is les ...

  2. iOS - OC NSTimer 定时器

    前言 @interface NSTimer : NSObject 作用 在指定的时间执行指定的任务. 每隔一段时间执行指定的任务. 1.定时器的创建 当定时器创建完(不用 scheduled 的,添加 ...

  3. iOS 定时器 NSTimer、CADisplayLink、GCD3种方式的实现

    在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 然而,在iOS中有很多方法完成以上的任务,到底有多少种方法呢?经过查阅资 ...

  4. iOS 倒计时NSTimer

    项目中可能会遇到有些倒计时的地方 比方 手机验证的时候,验证码一般都会有一个时间限制,此时在输入验证码的地方就须要展示一个倒计时 详细实现方式是使用了iOS 自带的 NSTimer 上代码 首先新建 ...

  5. iOS 里面 NSTimer 防止 循环引用

    使用NSTimer的类 #import "TBTimerTestObject.h" #import "TBWeakTimerTarget.h" @interfa ...

  6. iOS - Swift NSTimer 定时器

    前言 public class NSTimer : NSObject 作用 在指定的时间执行指定的任务. 每隔一段时间执行指定的任务. 1.定时器的创建 当定时器创建完(不用 scheduled 的, ...

  7. iOS定时器NSTimer的使用方法

    1.初始化 + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelect ...

  8. 【转】IOS 计时器 NSTimer

    原文网址:http://blog.csdn.net/tangshoulin/article/details/7644124 1.初始化 + (NSTimer *)timerWithTimeInterv ...

  9. IOS系列——NStimer

    Timer经常使用的一些东西 1. 初始化 timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@select ...

随机推荐

  1. 06jQuery-06-AJAX

    1.JS的AJAX AJAX,Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求. 如果要让用户留在当前页面中,同时发出新的HTTP请求,就 ...

  2. angular之$watch方法详解

    在$apply方法中提到过脏检查,首先apply方法会触发evel方法,当evel方法解析成功后,会去触发digest方法,digest方法会触发watch方法. (1)$watch简介 在diges ...

  3. IE无法获得cookie,ie不支持cookie的解决办法,火狐支持

    发现用自己的电脑 IE7.0总是无法正常登录,别的电脑都可以. 每次登录后又被重定向回了登录页面. 可换成Firefox和google chrome 却一切OK,后来还把浏览器升级到IE8.0 问题依 ...

  4. 【京东详情页】——原生js爬坑之二级菜单

    一.引言 做京东详情页仿写的时候,要用原生js实现顶部菜单的二级菜单显示与隐藏事件的触发. 过程中遇到了一个坑,在这里与大家分享.要实现的效果如下: 二.坑 谁触发事件?显示.隐藏二级菜单       ...

  5. Object.defineProperty()方法的用法详解

    Object.defineProperty()函数是给对象设置属性的. Object.defineProperty(object, propertyname, descriptor); 一共有三个参数 ...

  6. 【Linux笔记(002) 】-- centos7 文档操作基本命令

    一.cd -- ChangeDirectory a) 切换到 /DemoLM/ 文件夹 b) 回到用户 Home 根目录:是哪个账户登录的就会进入哪个用户的根目录 二.pwd -- PrintWork ...

  7. 【小程序】微信小程序实现各种特效实例

    写在前面 最近在负责一个微信小程序的前端以及前后端接口的对接的项目,整体上所有页面的布局我都已经搭建完成,里面有一些常用的特效,总结一下,希望对大家和我都能有所帮助 实例1:滚动tab选项卡 先看一下 ...

  8. ThinkPHP5高阶实战教程

    tp5项目:https://www.kancloud.cn/mikkle/thinkphp5_study/396283

  9. Judge Route Circle

    Initially, there is a Robot at position (0, 0). Given a sequence of its moves, judge if this robot m ...

  10. 20.Linux-USB鼠标驱动

    在上一章分析完USB总线驱动程序后, 接下来开始写一个USB驱动: 本节目的: 将USB鼠标的左键当作L按键,将USB鼠标的右键当作S按键,中键当作回车按键 参考/drivers/hid/usbhid ...