OC底层原理探索-NSRunLoop
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OC底层原理探索-NSRunLoop相关的知识,希望对你有一定的参考价值。
参考技术A这张图是苹果官网中图,接下来通过示例理解这种图
首先测试下 NStimer ,断点bt下
测试下 block
这里就不一一进行测试了,给出其余几种情况
在 CFRunLoop 源码中找到 CFRunLoopGetMain 和 CFRunLoopGetCurrent 方法
进入 _CFRunLoopGet0 方法
创建RunLoop是使用的__CFRunLoopCreate函数,查看函数实现:
由这个结构体,可以得知一个 runLoop 对应 _commonModes ,这个 _commonModes 是个集合类型,所以一个runLoop对应多个 mode
mode定义
__CFRunLoopMode 源码定义中包括了4个set集合 _sources0、_sources1、_observers、_timers ,这四个集合也就是我们常说的事件(事务)。所以我们可以得出结论:CFRunLoopMode和sourses、timer、observer也是一对多的关系。
这里的 timer、observer 比较好理解,什么是 _sources0、_sources1 呢?
mode类型
- kCFRunLoopDefaultMode 默认的运行模式,通常主线程是在这个Mode下运行
- UITrackingRunLoopMode 界面跟踪Mode,用于ScrollView等视图,追踪触摸滑动,保证界面的滑动不受其他Mode的影响
- UIInitializationRunLoopMode 在刚启动App时进入的第一个Mode,启动完成后就不在使用
- GSEventReceiveRunLoopMode 接受系统时间的内部Mode,通常用不到
- kCFRunLoopCommonModes 是一个伪模式,可以在标记为CommonModes的模式下运行,RunLoop会自动将_commonModeItems里的source、observe、timer同步到具有标记的Mode里。
在源码中查找 CFRunLoopRunSpecific 的方法实现,见下图:
下图就是上图的处理逻辑
【总结】
RunLoop是通过系统内部维护的循环进行事件、消息管理的一个对象。 RunLoop 实际上就是一个 do...while 循环,有任务时开始,无任务时休眠。本质是通过 mach_msg() 函数接收、发送消息。
CFRunLoopModeRef 这样设计有什么好处?Runloop为什么会有多个 Mode?
-Mode 做到了屏蔽的效果,当RunLoop运行在 Mode1 下面的时候,是处理不了 Mode2 的事件的;
比如NSDefaultRunLoopMode默认模式和UITrackingRunLoopMode滚动模式,滚动屏幕的时候就会切换到滚动模式,就不用去处理默认模式下的事件了,保证了 UITableView等的滚动顺畅。
RunLoop与线程的关系:
RunLoop中涉及到5个重要的类:
CFRunLoop - RunLoop对象
CFRunLoopMode - 五种运行模式
CFRunLoopSource - 输入源/事件源,包括Source0和Source1
CFRunLoopTimer - 定时源,也就是NSTimer
CFRunLoopObserve - 观察者,用来监听RunLoop
CFRunLoopSource - 事件源
CFRunLooTimer - 定时源
就是NSTimer,在预设的时间点唤醒RunLoop执行回调。因为它是基于RunLoop的,因此它不是实时的(Timer是不准确的,因为RunLoop只负责分发源消息。如果线程当前正在处理繁重的任务,就有可能导致Timer本次延时,或者少执行一次)。
CFRunLoopObserver - 观察者
用来监听时间点事件CFRunLoopActivity。
为什么main函数能够保持一直存在且不退出?
在main函数内容会调用UIApplication函数,而在UIAPPlicationMain内部会启动主线程的RunLoop,可以做到有消息处理,能够迅速从内核态到用户态的切换,立刻唤醒处理,而没有消息处理时,通过用户态到内核态的切换进入等待状态,避免资源的占用。因此main函数能够一直存在并且不退出。
NSRunLoop 和 CFRunLoopRef 区别
Runloop的mode作用是什么?
mode主要是用于指定RunLoop中事件优先级的
以上是关于OC底层原理探索-NSRunLoop的主要内容,如果未能解决你的问题,请参考以下文章