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

转载自点击打开链接

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

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    

    //NSObject的方法创建一个多线程

    [selfperformSelectorInBackground:@selector(multiThread)withObject:nil];

    

    self.window.backgroundColor = [UIColor whiteColor];

    [self.window makeKeyAndVisible];

    

    returnYES;

}


- (void)multiThread

{

    NSAutoreleasePool *pool = [[NSAutoreleasePoolalloc]init];

    

    if(![NSThreadisMainThread]) {

        //1种方式

        //此种方式创建的timer已经添加至runloop

        

        //[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];

        

        //保持线程为活动状态,才能保证定时器执行

        //[[NSRunLoop currentRunLoop] run];//已经将nstimer添加到NSRunloop中了

        

        //2种方式

        

        //此种方式创建的timer没有添加至runloop

        

        NSTimer *timer = [NSTimertimerWithTimeInterval:1.0ftarget:selfselector:@selector(timerAction)userInfo:nilrepeats:YES];

        

        //将定时器添加到runloop

        [[NSRunLoopcurrentRunLoop]addTimer:timerforMode:NSDefaultRunLoopMode];

        

        [[NSRunLoopcurrentRunLoop]run];

        

        NSLog(@"多线程结束");

    }

    [pool release];

}


- (void)timerAction

{

    //定时器也是在子线程中执行的

    if(![NSThreadisMainThread]) {

        NSLog(@"定时器");

    }

}


理解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 = [NSTimerscheduledTimerWithTimeInterval:1.0target:selfselector:@selector(timer:)userInfo:nilrepeats:YES];

    NSRunLoop *runLoop = [NSRunLoopcurrentRunLoop];

    [runLoop addTimer:myTimerforMode: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事件了。具体代码如下:

NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timer:) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoopaddTimer:timer forMode:NSRunLoopCommonModes];

大家可以参看博文http://bluevt.org/?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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值