1、RunLoop概念
RunLoop是通过内部维护的事件循环来对事件/消息进行管理的一个对象
- 没有消息需要处理时,休眠以避免资源占用(用户态 -> 内核态)
- 有消息需要处理时,立即被唤醒(内核态 -> 用户态)
2、数据结构
NSRunLoop是CFRunLoop的封装,提供了面向对象的API
- CFRunLoop
- CFRunLoopMode
- Source/Timer/Observer
CFRunLoopSource
- source0 需要手动唤醒线程
- source1 具备唤醒线程的能力
CFRunLoopTimer
基于事件的定时器
CFRunLoopOberver
观测时间点
- kCFRunLoopEntery
- kCFRunLoopBeforeTimer
- kCFRunLoopBeforeSources
- kCFRunLoopBeforeWaiting
- kCFRunLoopAfterWaiting
- kCFRunLoopExit
NSRunLoopCommonModes
- CommonMode不是实际存在的Mode
- 是同步Source/Timer/Observer到多个Mode中的一种技术方案
3、事件循环机制
4、RunLoop与NSTimer
滑动TableView时RunLoop发生Mode切换,由kCFRunLoopDefaultMode切换为UITrackingRunLoopMode,要确保Timer事件的正常运行,需要同时添加到两种mode下
void CFRunLoopAddTimer(runLoop, timer. commonMode)
5、RunLoop与多线程
线程与RunLoop一一对应; 自己创建的线程默认是没有RunLoop的
如何实现常驻线程?
- 当前线程开启RunLoop
- 向RunLoop添加Port/Source等维持RunLoop的事件循环
- 启动RunLoop
+ (NSThread *)_networkThread
{
static NSThread *thread = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
thread = [[NSThread alloc] initWithTarget:self, selector:@selctor(_networkThreadMain:) object:nil];
if ([thread respondsToSelector:@selector(setQualityService:)]) {
thread.qualityOfService = NSQualityServiceBackground;
}
[thread start];
})
}
+ (void)_networkThreadMain:(id)object
{
@autoreleasePool {
[[NSThread currentThread] setName:@"threadMain"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMatchPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}