Runloop

作者: NJKNJK | 来源:发表于2021-04-10 11:52 被阅读0次

    4Runloop 在object中提供了两个框架:

    CFRunLoopRef 是线程安全的

    NSRunLoop是线程不安全的

    线程和Runloop是一一对应的, 只能在当前的线程里获取当前现成的Runloop(主线程除外)

    每一个线程有个对应的Runloop 要想让线程一直执行不死掉就要开启自己的Runloop

    在Runloop中 提供了5中mode 每一个mode都有自己的Source 和Observer 还有Timer

    在执行不同的Mode的时候不同的Mode之间不会互相干扰。

    image

    每一个runloop都有若干个mode 每个mode理的资源都是不相互影响的

    runloop的应用

    1.AutoReleasePool

    在App启动之后 在主线里面会注册两个Observer 回调都是 _wrapRunLoopWithAutoreleasePoolHandler()

    第一个 Observer 监视的事件是 Entry(即将进入Loop),其回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池。其 order 是-2147483647,优先级最高,保证创建释放池发生在其他所有回调之前。

    第二个 Observer 监视了两个事件: BeforeWaiting(准备进入休眠) 时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池;Exit(即将退出Loop) 时调用 _objc_autoreleasePoolPop() 来释放自动释放池。这个 Observer 的 order 是 2147483647,优先级最低,保证其释放池子发生在其他所有回调之后。

    在主线程执行的代码,通常是写在诸如事件回调、Timer回调内的。这些回调会被 RunLoop 创建好的 AutoreleasePool 环绕着,所以不会出现内存泄漏,开发者也不必显示创建 Pool 了。

    2.事件响应

    3.界面更新

    4.手势识别

    界面更新和手势识别都是通过在Runloop里面添加Observer事件来进行监听的

    5.定时器

    NStimer 既CFRunLoopTimerRef

    它们之间是通过桥接的。一个NSTimer注册到Runlooper之后会给它在重复的时间点注册好事件。timer有一个属性叫做事Tolerance 表示到了当前时间点后容许有多少误差

    (CAdisolayLink)了解

    6.关于PerformSelecter

    NSObject 的 performSelecter:afterDelay:

    performSelector:onThread:

    这两个方法在调用的时候都会被添加到对应的线程之中的RunLoop中 如果当前的Runloop没有开启那么会失效

    关于GCD

    实际上 RunLoop 底层也会用到 GCD 的东西,比如 RunLoop 是用 dispatch_source_t 实现的 Timer(评论中有人提醒,NSTimer 是用了 XNU 内核的 mk_timer,我也仔细调试了一下,发现 NSTimer 确实是由 mk_timer 驱动,而非 GCD 驱动的)。但同时 GCD 提供的某些接口也用到了 RunLoop, 例如 dispatch_async()。

    当调用 dispatch_async(dispatch_get_main_queue(), block) 时,libDispatch 会向主线程的 RunLoop 发送消息,RunLoop会被唤醒,并从消息中取得这个 block,并在回调 CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE() 里执行这个 block。但这个逻辑仅限于 dispatch 到主线程,dispatch 到其他线程仍然是由 libDispatch 处理的。

    相关文章

      网友评论

          本文标题:Runloop

          本文链接:https://www.haomeiwen.com/subject/bujhhltx.html