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

理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的。

先看看NSTimer的两个常用方法:

+ (NSTimer*)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;//生成timer但不执行

+ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;//生成timer并且纳入当前线程的run loop来执行

NSRunLoop与timer有关方法为:

– (void)addTimer:(NSTimer*)timer forMode:(NSString*)mode;//在run loop上注册timer

主线程已经有run loop,所以NSTimer一般在主线程上运行都不必再调用addTimer:。但在非主线程上运行必须配置run loop,该线程的main方法示例代码如下:

– (void)main

{

  NSTimer *myTimer =[NSTimer scheduledTimerWithTimeInterval:1.0target:selfselector:@selector(timer:)userInfo:nilrepeats:YES];

  NSRunLoop *runLoop =[NSRunLoopcurrentRunLoop];

  [runLoop addTimer:myTimer forMode:NSDefaultRunLoopMode]; //实际上这步是不需要,scheduledTimerWithTimeInterval已经纳入当前线程运行。如果使用timerWithTimeInterval则需要

  while (condition)

    [runLoop run];

}

实际上这个线程无法退出,因为有timer事件需要处理,[runLoop run]会一直无法返回。解决办法就是设置一个截止时间:

[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]];//每隔10秒检查下线程循环条件,当然时间值可以根据实际情况来定。

我们通常在主线程中使用NSTimer,有个实际遇到的问题需要注意。当滑动界面时,系统为了更好地处理UI事件和滚动显示,主线程runloop会暂时停止处理一些其它事件,这时主线程中运行的NSTimer就会被暂停。解决办法就是改变NSTimer运行的mode(mode可以看成事件类型),不使用缺省的NSDefaultRunLoopMode,而是改用NSRunLoopCommonModes,这样主线程就会继续处理NSTimer事件了。具体代码如下:

timerWithTimeIntervalselectoruserInfo

forMode

大家可以参看博文?p=209,,加深理解NSTimer和NSRunLoop的关系。

以前博文中提到延迟调用的方法,其实就是在当前线程的run loop上注册timer来实现定时运行的。所以如果是在非主线程上使用,一定要有一个run loop。

– (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray*)modes;

– (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

你的选择是做或不做,但不做就永远不会有机会

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

相关文章:

你感兴趣的文章:

标签云: