RunLoop学习总结
RunLoop的定义
当有持续的异步任务需求时,我们会创建一个独立的生命周期可控的线程。RunLoop就是控制线程生命周期并接收事件进行处理的机制。
RunLoop是iOS事件响应与任务处理最核心的机制,它贯穿整个系统。
使用RunLoop的目的
通过RunLoop机制实现省电,流畅,响应速度快,用户体验好
特性
- 主线程的RunLoop在应用启动时会自动创建
- 其它线程则需要在该线程下自己启动
- RunLoop并不是线程安全的,所以需要避免在其它线程上调用当前线程的RunLoop
- RunLoop负责管理AutoRelease Pools
- RunLoop负责处理消息事件,即输入源事件和计时器事件
RunLoop机制
主线程(有RunLoop的线程)几乎所有的函数都从以下六个之一的函数调起:
- CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION
用于向外部报告RunLoop当前状态的更改,框架中很多机制都由RunLoopObserver触发,如 CAAnimation
- CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK
消息通知、非延迟的Perform、Dispatch调用、Block调用、KVO
- CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE
- CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION
延迟的Perform, 延迟Dispatch 调用
- CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION
处理APP内部事件、App自己负责管理(触发),如 UIEvent 、CFSocket。普通函数调 用、系统调用
- CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION
由RunLoop和内核管理,Mach Port驱动,如CFMachPort、CFMessagePort
主要有以下六种状态:
kCFRunLoopEntry -- 进入runloop循环
kCFRunLoopBeforeTimers -- 处理定时调用前回调
kCFRunLoopBeforeSources -- 处理input sources的事件
kCFRunLoopBeforeWaiting -- runloop睡眠前调用
kCFRunLoopAfterWaiting -- runloop唤醒后调用
kCFRunLoopExit -- 退出runloop
RunLoop Modes
RunLoop Mode 就是流水线上支持生产的产品类型,流水线在一个时刻只能在一种模式下运行, 生产某一类型的产品。消息事件就是订单。
Cocoa 定义了4种Mode
NSDefaultRunLoopMode 默认模式,在没有指定Mode的时候,默认
UITrackingRunLoopMode 拖动事件
NSRunLoopCommonModes 是一个模式集合,当绑定一个事件源到这个模式集合的时候就相当于绑定到了集合内的每一个模式。
在主线程启动一个计时器Timer,然后拖动UITableView或者UIScrollView,计时器不执行。这是因为,为了更好的用户体验,在主线程中 Event Tracking 模式的优先级最高。在用户拖动控件时,主线程的Run Loop是运行在Event Tracking Mode下,而创建的Timer是默认关联为Default Mode,因此系统不会立即执行Default Mode下接收的事件。解决方法:
要么加到集合中的每一个模式,要么就和UITableView一样的 Tracking 模式下。
未完待续,后面会实践中学习并更新上来