iOS之 NSTimer(一)
以前没怎么了解过这个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
当使用NSTimer
的scheduledTimerWithTimeInterval
方法时。事实上此时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(一)的更多相关文章
- iOS定时器-- NSTimer 和CADisplaylink
iOS定时器-- NSTimer 和CADisplaylink 一.iOS中有两种不同的定时器: 1. NSTimer(时间间隔可以任意设定,最小0.1ms)// If seconds is les ...
- iOS - OC NSTimer 定时器
前言 @interface NSTimer : NSObject 作用 在指定的时间执行指定的任务. 每隔一段时间执行指定的任务. 1.定时器的创建 当定时器创建完(不用 scheduled 的,添加 ...
- iOS 定时器 NSTimer、CADisplayLink、GCD3种方式的实现
在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 然而,在iOS中有很多方法完成以上的任务,到底有多少种方法呢?经过查阅资 ...
- iOS 倒计时NSTimer
项目中可能会遇到有些倒计时的地方 比方 手机验证的时候,验证码一般都会有一个时间限制,此时在输入验证码的地方就须要展示一个倒计时 详细实现方式是使用了iOS 自带的 NSTimer 上代码 首先新建 ...
- iOS 里面 NSTimer 防止 循环引用
使用NSTimer的类 #import "TBTimerTestObject.h" #import "TBWeakTimerTarget.h" @interfa ...
- iOS - Swift NSTimer 定时器
前言 public class NSTimer : NSObject 作用 在指定的时间执行指定的任务. 每隔一段时间执行指定的任务. 1.定时器的创建 当定时器创建完(不用 scheduled 的, ...
- iOS定时器NSTimer的使用方法
1.初始化 + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelect ...
- 【转】IOS 计时器 NSTimer
原文网址:http://blog.csdn.net/tangshoulin/article/details/7644124 1.初始化 + (NSTimer *)timerWithTimeInterv ...
- IOS系列——NStimer
Timer经常使用的一些东西 1. 初始化 timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@select ...
随机推荐
- MySQL 经典面试题
MySQL 面试 1 存储过程 什么是存储过程 存储过程是一些编译好的SQL语句 因为系统在调用SQL的时候比较浪费时间,所以之前先将一些基本的额SQL语句代码进行编译(对单表或多表的增删改查),然后 ...
- AngularJS–Scope(作用域)
点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ Scope Scope 是一个应用程序的模块的对象.它是表达式的执行上下文.它充斥在DO ...
- java基础解析系列(七)---ThreadLocal原理分析
java基础解析系列(七)---ThreadLocal原理分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)-- ...
- 【Spring】高级装配
前言 前面讲解了bean的核心装配技术,其可应付很多中装配情况,但Spring提供了高级装配技术,以此实现更为高级的bean装配功能. 高级装配 配置profile bean 将所有不同bean定义放 ...
- An Introduction to Variational Methods (5.2)
我们现在已经得到了关于潜在变量Z的优化分布的表达形式: 其中: 所以现在我们可以得到Z的期望: 另外对于Z还值得一提的是,我们从其优化分布的表达式中可以看出,各个Z的组成部分之间还是相互耦 ...
- ASP.NET没有魔法——ASP.NET MVC & 分层
上一篇文章简要说明了MVC所代表的含义并提供了详细的项目及其控制器.视图等内容的创建步骤,最终完成了一个简单ASP.NET MVC程序. 注:MVC与ASP.NET MVC不相等,MVC是一种开发模式 ...
- webpack2使用ch6-babel使用 处理es6 优化编译速度
1 目录结构 安装依赖 cnpm install --save-dev babel-loader babel-core babel-preset-env babel-preset-latest &qu ...
- wmic命令
WMIC扩展WMI(Windows Management Instrumentation,Windows管理工具) ,提供了从命令行接口和批命令脚本执行系统管理的支持. 一.如何使用帮助文档: 1.w ...
- ubuntu远程桌面介绍
一.windows远程ubuntu14.04 由于xrdp.gnome和unity之间的兼容性问题,在Ubuntu 14.04版本中仍然无法使用xrdp登陆gnome或unity的远程桌面,现象是登录 ...
- Github Page+Bmob实现简单动态功能
Github Page基于jekyll能够实现简单的静态网站,但是没有提供后端服务.目前国内外也有很多提供后台服务,特别是云服务.譬如国外有AWS,记得好像是注册免费使用一年:再如Heroku,支持N ...