NSTimer和Runloop的关系

什么是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就是一个能在从现在开始的后面的某一个时刻或者周期性的执行我们指定的方法的对象。

NSTimer怎样保证参数的生命周期

NSTimer可以选择是否重复执行,为了保证NSTimer调用的方法中传递的对象生命周期,NSTimer会对外界传递的对象进行一次retain。
如果是一次性调用的NSTimer,会在本次调用完毕之后invalidate掉NSTimer自身,而NSTimer做retain的对象也会被进行一次release。但是如果是多次重复调用的NSTimer,就需要我们自己在某个特定的时刻来invalidate掉NSTimer,这个invalidate的时刻是根据我们代码情况来自己决定的,否则将会一直存在。

下面的方法我们先创建了一个Object对象,然后添加了一个timer(关于NSTimer和runloop后面再讲),并且进行了一次release,这时object并没有被释放,而是被NSTimer进行了一次retain,我们通过在Object的dealloc方法中打印就可以知道是否被释放。
在本次NSTimer的timer所调用方法调用完毕之后,NSTimer会invalidate自身,而object对象也会被释放。

  Object *object = [[Object alloc] init];
  [NSTimer scheduledTimerWithTimeInterval:5 target:object   selector:@selector(timerAction:) userInfo:nil repeats:NO];
  [object release];

而通过下面这种方式创建的timer就不会被NSTimer自动释放,因为这次调用是重复调用,必须我们显示的进行invalidate,NSTimer才会消失,这时obect对象也就会释放了。

  Object *object = [[Object alloc] init];
  [NSTimer scheduledTimerWithTimeInterval:5 target:object selector:@selector(timerAction:) userInfo:nil repeats:YES];
  [object release];

总结:
如果使用重复的NSTimer一定要有对应的invalidate,否则timer会一直存在。
NSTimer会对target对象进行一次retain,所以我们要注意target对象的生命周期。

NSTimer的实时性

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

NSTimer与Runloop的关系

我们前面做演示的代码创建的NSTimer会默认为我们添加到Runloop的default mode中,而且由于是在主线程中,所以Runloop是开启的,不需要我们手动打开。
在我们进行多线程编程时,所有的source都需要添加到Runloop中才能生效,对于我们的NSTimer当然也需要添加到Runloop中才能生效。如果一个Runloop中没有任何source的话,会立即退出的。而主线程的Runloop在程序运行时,系统就已经为我们添加了很多source到Runloop中,所以主线程的Runloop是一直存在的,我们可以通过打印mainThread中的Runloop来查看所包含的source。

下面的代码就没有添加到Runloop中,所以这个NSTimer永远也不会发生作用,这是一份错误的代码示例。

  Object *object = [[Object alloc] init];
  NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1] interval:1 target:object selector:@selector(timerAction:) userInfo:nil repeats:NO];
  [object release];
NSTimer添加到Runloop中,但是不运行

在iOS多线程中,每一个线程都有一个Runloop,但是只有主线程的Runloop默认是打开的,其他子线程也就是我们创建的线程的Runloop默认是关闭的,需要我们手动运行。
我们可以通过[NSRunLoop currentRunLoop]来获得当前线程的Runloop,并且调用
[runloop addTimer:timer forMode:NSDefaultRunLoopMode]方法将定时器添加到runloop中,最后一定不要忘记调用runloop的run方法将当前runloop开启,否则NSTimer永远也不会运行。

除了上面的问题,还有一个问题就是Mode选择不正确,这种情况比较少见,可以参考以下博客:
http://www.mgenware.com/blog/?p=459

时间: 2024-10-05 14:54:11

NSTimer和Runloop的关系的相关文章

iOS之 NSTimer

以前没怎么了解过这个NSTimer,其实还是有挺多坑的,今天来总结一下: 首先我们一起来看这个: 我在A  -> (push) -> B控制器,然后再B控制器中开启了一个NSTimer.然后我又pop到A pop到A的时候,定时器还在运行,并且B没有被释放(未调用dealloc).why? 这就不得不让我联想到我上篇写到的 “常驻线程”了,莫非NSTimer也是添加到了RunLoop? 这说明本例中的NSTimer确实是跑在了NSRunLoop中. 那为什么B没有释放呢? Timer对Targ

利用runLoop加载高清大图

一.什么是runLoop 1.说白了,runloop就是运行循环 2.runloop,他是多线程的法宝 通常来讲,一个线程一次只能执行一个任务,执行完之后就退出线程.但是,对于主线程是不能退出的,因此我们需要让主线程即使任务执行完毕,也可以继续等待接收事件而不退出,那么runloop就可以做到. 但是非主线程通常来说就是为了执行某一任务的,执行完毕就需要归还资源,因此默认是不运行runloop的. 3.每一个线程对应都有一个runloop,只是默认只有主线程的runloop是开启的,其他子线程的

将NSTimer添加至RunLoop中的两种方法区别

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {     self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];          //用NSObject的方法创建一个多线程     [self p

RunLoop总结:RunLoop基础知识

没有实际应用场景,很难理解一些抽象空洞的东西,所以前面几篇文章先介绍了RunLoop的几个使用场景. 另外AsyncDisplayKit中也有大量使用RunLoop的示例. 关于实际的使用RunLoop 的案例和使用场景就不总结了,今天总结一点RunLoop的基础知识和概念. 什么是RunLoop? 顾名思义,它就是一个运行循环.一个RunLoop 就是一个用于处理既定工作和接收到的外来事件的事件处理循环.RunLoop的存在目的就是当线程中有任务时,保证线程忙着干活:当线程中没有任务时,让线程

iOS runtime和runloop

runtime 和 runloop 作为一个程序员进阶是必须的,也是非常重要的, 在面试过程中是经常会被问到的, 所以大家有必要进行研究,有能力的童鞋可以和下面作者一样, 亲历实践一下. 在简书里发现了两篇非常好的文章介绍 runtime和runloop的,在这里合二为一了, 把原版作者的东西拿了过来, 为了尊重作者,在这里注明一下 @sam_lau 是runtime的作者, @tripleCC是runloop的作者   RunTime Objective-C是基于C语言加入了面向对象特性和消息

iOS多线程的初步研究(四)-- NSTimer

 iOS多线程的初步研究(四)-- NSTimer 原文地址  http://www.cnblogs.com/sunfrog/p/3243230.html 理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的. 先看看NSTimer的两个常用方法: + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelec

关于 NSTimer 和 NSRunLoop 的一些理解

一:NSTimer和NSRunLoop的关系? 只要出现NSTimer必须要有NSRunLoop,NSTimer必须依赖NSRunLoop才能执行 .NSTimer其实也是一种资源,如果看过多线程编程指引文档的话,我们会发现所有的source如果要起作用,就得加到runloop中去.同理timer这种资源要想起作用,那肯定也需要加到runloop中才会生效喽.如果一个runloop里面不包含任何资源的话,运行该runloop时会立马退出.你可能会说那我们APP的主线程的runloop我们没有往其

Runloop笔记

原文:Runloop基础元素解析 http://www.jianshu.com/p/8b9c81a521bc?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weixin-timeline&from=timeline&isappinstalled=0 作用:保持程序运行,处理各类事件,节省CPU资源提高程序性能.没有事件时就进入休眠状态. 一个Thread对应一个一个runl

深入理解iOS开发之RunLoop

RunLoop属于iOS进阶开发中的一个重要技术点,本文会重点讲解我在开发过程中总结的对RunLoop的理解. RunLoop概念 RunLoop是与多线程相关的一个事件处理机制,用来调度操作和处理协调即将发生的事件.iOS Developer Library关于RunLoop的解释是,RunLoop机制的四个作用: RunLoop的管理并不是自动进行的,你需要编写线程代码去开始一个RunLoop,并在合适的时机响应事件.但是Cocoa和Core Foundation库都提供了RunLoop对象