RunLoop

473 阅读1分钟

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];
    }
}