Runloop
2023-04-22 本文已影响0人
请叫我小鹏哥儿
本质
RunLoop本质上是一个对象,这个对象可以保持程序的持续运行并且处理程序中的各种事件(如触摸事件,定时器时间,selector事件).
RunLoop没有事情处理时就会使线程进入睡眠状态.这样可以节省CPU资源,提高程序性能.
和线程的关系
线程用来执行一个或者多个任务,执行完成后就会退出,再有任务也无法继续执行。
runloop,让线程不断的执行任务,当没有任务的时候,进入休眠状态,等待任务的到来。
每条线程都有唯一的一个RunLoop对象。
RunLoop保存在一个全局的 Dictionary里,线程作为key, RunLoop作为 value。
线程刚创建时并没有 RunLoop对象, RunLoop会在第一次获取它时创建。
RunLoop会在线程结束时销毁。
主线程的 RunLoop已经自动获取,子线程默认没有开启 Runloop。
底层数据结构
RunLoop的数据结构主要有三种:
CFRunLoop、CFRunLoopMode、Source/Timer/Observer
CFRunLoop.png
CFRunLoopMode.png
Source:Timer:Observer.png
几种运行模式(mode)?每个运行模式下面的 CFRunloopMode 是哪些?他们分别是什么职责?
- kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
- UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
- UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用,会切换到kCFRunLoopDefaultMode
- GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
- kCFRunLoopCommonModes: 这是一个占位用的Mode,作为标记kCFRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一种真正的Mode
监听状态有哪几种
- kCFRunLoopEntry:RunLoop进入运行循环状态。
- kCFRunLoopExit:RunLoop退出运行循环状态。
- kCFRunLoopBeforeTimers:RunLoop即将处理定时器事件。
- kCFRunLoopBeforeSources:RunLoop即将处理事件源事件。
- kCFRunLoopBeforeWaiting:RunLoop即将进入睡眠等待状态。
- kCFRunLoopAfterWaiting:RunLoop被唤醒并处理完事件后即将进入下一个循环状态。
- kCFRunLoopAllActivities:监听所有状态。
工作流程
流程.png- 通知 observer,进入runloop
- 通知 observer,即将处理 timer 事件
- 通知 observer,即将处理 source 事件
- 处理block,runloop 是可以添加 block 的(CFRunLoopPerformBlock(<#CFRunLoopRef rl#>, <#CFTypeRef mode#>, <#^(void)block#>))
- 处理 source 0
- 处理 source1事件,如果存在就处理,跳转到第8
- 通知 observer 即将休眠
- 通知 observer 结束休眠(timer 事件,source1 事件等)
- 然后根据前面的执行结果,决定是否再次循环
应用场景
保证线程的长时间存活
滚动视图流畅性优化
让Timer正常运转
事件响应、手势识别、界面刷新、AutoreleasePool自动释放池、NSTimer、PerformSelecter、GCD、网络请求底层等都用到了RunLoop