1.NSRunloop基本概念
@Run loops 是线程相关的基础框架的一部分.一个run loop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件.
@线程的生命周期存在五个状态:新建,就绪,运行,阻塞,死亡
@NSRunLoop可以保持一个线程一直为活动状态,不会马上被销毁掉,在多线程中,子线程就不会被销毁
2.NSRunloop常用方法
+ (NSRunLoop *)currentRunLoop; //获得当前线程的run loop
+ (NSRunLoop *)mainRunLoop; //获得主线程的run loop
- (void)run; //进入处理事件循环,如果没有事件则立刻返回。注意:主线程上调用这个方法会导致无法返回(进入无限循环,虽然不会阻塞主线程),因为主线程一般总是会有事件处理。
- (void)runUntilDate:(NSDate *)limitDate; //同run方法,增加超时参数limitDate,避免进入无限循环。使用在UI线程(亦即主线程)上,可以达到暂停的效果。
- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate; //等待消息处理,好比在PC终端窗口上等待键盘输入。一旦有合适事件(mode相当于定义了事件的类型)被处理了,则立刻返回;类同run方法,如果没有事件处理也立刻返回;有否事件处理由返回布尔值判断。同样limitDate为超时参数。
- (void)acceptInputForMode:(NSString *)mode beforeDate:(NSDate *)limitDate; //似乎和runMode:差不多(测试过是这种结果,但确定是否有其它特殊情况下的不同),没有BOOL返回值。
官网文档也提到run和runUntilDate:会以NSDefaultRunLoopMode参数调用runMode:来处理事件。
当程序运行后,主线程自动启动一个run loop,而多线程则需要手动来启动run loop。
3.定时器在多线程中的使用
@在多线程中使用定时器必须手动开启Runloop
@代码示例:
[NSThread detachNewThreadSelector:@selector(onclick) toTarget:self withObject:nil];
- (void)onclick{
// 子线程,需要手动加入一个释放池,来释放通过便利构造器创建的对象,主线程自动添加了
@autoreleasepool {
/**
* 注意这2个初始化方法的区别
* 实例方法创建的NSTimer,需要手动加入Runloop中,便利构造器创建NSTimer,自动添加了
NSTimer * timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(ontime) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
*/
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(ontime) userInfo:nil repeats:YES];
// 开启Runloop来使线程保持存活状态
[[NSRunLoop currentRunLoop] run];
}
}
4.调用主线程的run loop的各种方式
[[NSRunLoop mainRunLoop] run]; //主线程永远等待,但让出主线程时间片
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate distantFuture]]; //等同上面调用
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate date]]; //立即返回
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; //主线程等待,但让出主线程时间片,然后过10秒后返回
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]]; //主线程等待,但让出主线程时间片;有事件到达就返回,比如点击UI等。
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate date]]; //立即返回
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate dateWithTimeIntervalSinceNow:10.0]]; //主线程等待,但让出主线程时间片;有事件到达就返回,如果没有则过10秒返回。