首页 > 代码库 > NSTimer
NSTimer
此篇文章参考自
https://i.cnblogs.com/EditPosts.aspx?opt=1
http://blog.csdn.net/enuola/article/details/8099461
NSTimer官方解释:“A timer provides a way to perform a delayed action or a periodic action. The timer waits until a certain time interval has elapsed and then fires, sending a specified message to a specified object. ”翻译过来就是timer就是一个能在从现在开始的后面的某一个时刻或者周期性的执行我们指定的方法的对象。
timer会在未来的某个时刻执行一次或者多次我们指定的方法。
(1)如何保证timer在未来的某个时刻触发指定事件的时候,使我们指定的方法有效的
解决方法:将指定给timer的方法的接收者retain一份就搞定了,实际上系统也是这样做的。不管是重复性的timer还是一次性的timer都会对它的方法的接收者进行retain,这两种timer的区别在于“一次性的timer在完成调用以后会自动将自己invalidate,而重复的timer则将永生,直到你显示的invalidate它为止”。
(2)iOS中定时器的开启与关闭
一次计时器:
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(scrollTimer) userInfo:nil repeats:NO];
重复计时:
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(function:) userInfo:nil repeats:YES];
将计数器的repeats设置为YES的时候,self的引用计数会加1。因此可能会导致self(即viewController)不能release,所以,必须在viewWillAppear的时候,将计数器timer停止,否则可能会导致内存泄露。
停止timer:这个是永久的停止
注意:停止后,一定要将timer赋空,否则还是没有释放
[timer invalidate];
timer = nil;
(3)如果想要实现:先停止,然后再某种情况下再次开启运行timer,可以使用下面的方法
//关闭定时器
[myTimer setFireDate:[NSDate distantFuture]];
用下面的方法再次开启定时器:
//开启定时器
[myTimer setFireDate:[NSDate distantPast]];
例子:比如,在页面消失的时候关闭定时器,然后等页面再次打开的时候,又开启定时器。
(主要是为了防止它在后台运行,暂用CPU)可以使用下面的代码实现:
//页面将要进入前台,开启定时器
-(void)viewWillAppear:(BOOL)animated
{
//开启定时器
[scrollView.myTimer setFireDate:[NSDate distantPast]];
}
//页面消失,进入后台不显示该页面,关闭定时器
-(void)viewDidDisappear:(BOOL)animated
{
//关闭定时器
[scrollView.myTimer setFireDate:[NSDate distantFuture]];
}
(4)NSTimer能否准时触发事件
不能,NSTimer不是一个实时系统,不管是一次性的还是重复性的,NSTimer的触发时间都会与我们预想的触发事件有所出入,出入的大小与我们程序的执行情况有关;
比如可能程序是多线程的,而你的timer只是添加在某一个线程的runloop的某一种指定的runloopmode中,由于多线程通常都是分时执行的,而且每次执行的mode也可能随着实际情况发生变化。
假设你添加了一个timer指定2秒后触发某一个事件,但是签好那个时候当前线程在执行一个连续运算(例如大数据块的处理等),这个时候timer就会延迟到该连续运算执行完以后才会执行。重复性的timer遇到这种情况,如果延迟超过了一个周期,则会和后面的触发进行合并,即在一个周期内只会触发一次。但是不管该timer的触发时间延迟的有多离谱,他后面的timer的触发时间总是倍数于第一次添加timer的间隙。
(5)NSTimer添加到RunLoop
NSTimer其实也是一种资源,如果看过多线程编程指引文档的话,我们会发现所有的source如果要起作用,就得加到runloop中去。同理timer这种资源要想起作用,那肯定也需要加到runloop中才会生效喽。如果一个runloop里面不包含任何资源的话,运行该runloop时会立马退出。你可能会说那我们APP的主线程的runloop我们没有往其中添加任何资源,为什么它还好好的运行。
必须将timer添加到runloop才会生效
(6)添加到runloop不会触发事件的原因
第一个:runloop是否运行
每一个线程都有它自己的runloop,程序的主线程会自动的使runloop生效,但对于我们自己新建的线程,它的runloop是不会自己运行起来,当我们需要使用它的runloop时,就得自己启动。
第二个:mode是否正确
timer添加的时候,我们需要指定一个mode,因为同一线程的runloop在运行的时候,任意时刻只能处于一种mode。所以只能当程序处于这种mode的时候,timer才能得到触发事件的机会。
要让timer生效,必须保证该线程的runloop已启动,而且其运行的runloop mode也要匹配。
NSTimer