Runloop底层原理分析

原创文章
声明:作者声明此文章为原创,未经作者同意,请勿转载,若转载,务必注明本站出处,本平台保留追究侵权法律责任的权利。
全栈老韩
全栈工程师,擅长iOS App开发、前端(vue、react、nuxt、小程序&Taro)开发、Flutter、React Native、后端(midwayjs、golang、express、koa)开发、docker容器、seo优化等。

Runloop

  • Runloop一个运行循环,是一个对象.
  • 包含一个do while循环
  • 提供一个入口函数,程序可以进入一个do while循环
  • 消息机制处理模式

C: 运行->计算->完成->退出

作用:

  • 保持程序的持续进行
  • 处理app中的各种事件(触摸、定时器、performSelecor)
  • 节省cpu资源、提供程序的性能:该做事就做事,该休息就休息

处理

  • block应用: __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__

  • 调用timer用: __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__

  • 响应source0: __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__

  • 响应source1: __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__

  • GCD主队列: __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__

  • observer源: __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__

  • 线程和runloop通过key-value的形式一一对应.

  • 子线程的runloop默认不开启

  • 基于线程创建runloop

  • 通过变量 -- 线程 -- runloop -- timer

  • timer依赖于runloop

复制代码
NSThread *thread = [[NSThread alloc] initWithBlock:^{
    NSLog(@"%@", [NSThread currentThread]);
    [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^{
        NSLog(@"子线程timer");
        if (self.isStopping) {
            [NSThread exit];
        }
    }];
    [[NSRunloop currentRunLoop] run];
}];
thread.name = @"xxxxx";
[thread start];
  1. Timer为什么不准? \
  • 在default和tracking mode切换.
  1. 一个runloop对应多个mode,一个mode对应于多个timer,source,observers.
  2. timer是如何加入runloop?
    runLoopRun
    runLoopDoBlocks
    while循环执行item并执行timer等
    timer加入的mode和我们现在runloop的mode相等
    curr->_mode = KCFRunLoopCommonModes相等.
  • timer一定要加入到相应的runloop的mode, timer加到items
  • runloopRun -> doBlock -> while
  • item->next
  • doit
  • block调用
复制代码
-(void)cfTimerDemo {
    CFRunLoopTimerContext context = {
        0,
        ((__bridge void*)self),
        NULL,
        NULL,
        NULL
    };
    CFRunLoopRef rlp = CFRunLoopGetCurrent();
    /**
    参数一:用于分配对象的内存
    参数二:在什么时候触发(距离现在)
    参数三:每个多少时间出发一次
    参数四:未来参数
    参数五:CFRunLoopObserver的优先级 当在RunLoop同一运行阶段中有多个CFRunLoopObserver 正常情况下使用0
    参数六:回调,比如触发事件,我就会来到这里
    参数七:上下文记录信息
    */
    CFRunLoopTimerRef timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, 0, 1, 0, 0, lgRunLoopTimerCallBack, &context);
    CFRunLoopAddTimer(rlp, timerRef, kCFRunLoopDefaultMode);
}
void lgRunLoopTimerCallBack(CFRunLoopTimerRef timer, void *info) {
    NSLog(@"%@---%@", timer, info);
}
  1. observer
  • 监听runloop的状态.
  • 其demo和timer类似.
  1. source
  • source0,回调函数指针

  • 一个signal 待处理

  • wake up唤醒runloop处理事件

  • 作用:处理app内部事件

  • 作用:app自己负责管理的事务, 触摸事件等 UIEvent、CFSocket

  • source1 mach_port & 回调函数指针

  • runloop和内核管理

  • port

  • 线程之间通讯

  • 实用技巧:

  • 卡顿检测

  • FPS

暂无评论,快来发表第一条评论吧