将NSTimer加入至RunLoop中的两种方法差别


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
//用NSObject的方法创建一个多线程
[self performSelectorInBackground:@selector(multiThread) withObject:nil];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)multiThread
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (![NSThread isMainThread]) {
// 第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 = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
//将定时器加入到runloop中
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
NSLog(@"多线程结束");
}
[pool release];
}
- (void)timerAction
{
//定时器也是在子线程中运行的
if (![NSThread isMainThread]) {
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 =[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事件了。详细代码例如以下:

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

[[NSRunLoopcurrentRunLoop]addTimer:timerforMode: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;


优质内容筛选与推荐>>
1、普林斯顿《算法》笔记(三)
2、Django模板系统(非常详细)
3、C#学习(1)
4、EBS 清除高速缓存
5、如何在整个企业组织中整合与审计内容


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn