- 什么是RunLoop
RunLoop 是线程专属的事件循环机制
- 为什么要有RunLoop
普通子线程执行完代码会直接销毁,频繁创建 / 销毁线程损耗大量 CPU;RunLoop 给线程赋予「循环等待」能力
RunLoop 最精妙的设计在于它的「休眠-唤醒」机制。线程在没有事件时通过 mach_msg()系统调用进入内核休眠状态,几乎不消耗 CPU 资源。当有事件到来时(如触摸屏幕、Timer 到期、网络数据到达),内核会唤醒线程,RunLoop 继续处理事件。

- RunLoop和线程的关系
在 iOS 中,线程和 RunLoop 之间是严格的一一对应关系。这个映射关系被维护在一个全局的 Dictionary 中,key 是线程标识(pthread_t),value 是对应的 CFRunLoopRef。
关键特性:
-
主线程自动创建:主线程的 RunLoop 在 App 启动时就已经自动创建并启动,无需手动干预
-
子线程懒加载:子线程的 RunLoop 不会自动创建,只有当你第一次调用CFRunLoopGetCurrent()或 RunLoop.current 时才会创建
-
生命周期绑定:RunLoop 的生命周期与线程绑定。线程销毁时,其对应的 RunLoop 也会自动销毁
-
不能跨线程访问:你只能在当前线程内部获取其 RunLoop(主线程除外)
- RunLoop内部结构
RunLoop 的内部结构可以概括为:一个 RunLoop 包含多个 Mode,每个 Mode 包含多个 Item(Source、Timer、Observer)
具体结构如下图所示

其中pthread代表当前线程,modes存储当前RunLoop注册过的所有运行模式,currentMode代表当前运行的mode,而commonModes不是真实 Mode,是虚拟别名集合:给 Timer/Source 绑定 CommonModes 时,底层会自动把任务同时添加到集合内所有真实 Mode 中。

source0存放source0类型事件源
source1存放source1类型事件源
timers存放 CFRunLoopTimer 定时器
observer存放 CFRunLoopObserver 生命周期观察者
- 详细介绍RunLoop四大核心组件
1.mode
CFRunLoopMode
Mode 是 RunLoop 的事件隔离容器,所有 Source、Timer、Observer 都必须绑定指定 Mode 才能生效。
想象一下:你在滑动一个 TableView 时,希望滚动尽可能流畅。此时如果还有 Timer 不停地触发回调,或者网络请求的回调频繁更新 UI,就会导致滚动卡顿。Mode 的设计就是为了解决这个问题------滑动时 RunLoop 切换到「追踪模式」,暂停非必要的事件处理,将 CPU 资源优先用于渲染。
核心规则:同一时刻,RunLoop 只能运行在一种 Mode 下,切换 Mode 时,当前未处理的事件会暂时搁置
mode的运行模式
-
NSDefaultRunLoopMode:App 常规运行状态,页面静止、普通定时器、常规 UI 事件默认运行在此模式
-
UITrackingRunLoopMode:ScrollView、TableView 滑动时,主线程自动切换到此模式,DefaultMode 的所有任务会暂停
-
NSRunLoopCommonModes:重点!不是真实运行模式,它只是一个标记字符串。当你将某个 Mode 标记为 Common,或者将某个 Item 添加到 CommonModes 时:
-
Item 会被自动同步到所有标记为 Common 的 Mode 中
-
目前 DefaultMode 和 TrackingRunLoopMode 都已被标记为 Common
-
2.CFRunLoopSource 事件源
source 是 RunLoop 待处理的任务载体,分为两类,底层唤醒逻辑完全不同: Source0:App 自定义事件
-
无内核 Mach 端口,无法唤醒休眠的 RunLoop
-
需要手动标记待处理状态,仅 RunLoop 唤醒后才能执行
-
场景:无延时 performSelector、自定义手势、UI 交互事件
Source1:内核驱动事件
-
绑定系统 Mach 端口,内核可主动发信号,可直接唤醒休眠的 RunLoop
-
场景:主线程 GCD 异步、网络回调、硬件触摸事件、延时 performSelector
3.CFRunLoopTimer 定时器
NSTimer 的底层本质就是 CFRunLoopTimer,完全依赖 RunLoop Mode 运行。
致命特性:定时器绑定指定 Mode,RunLoop 切换 Mode 时,定时器会暂停计时。这也是「列表滑动时 NSTimer 失效」的根本原因。
4.CFRunLoopObserver 生命周期观察者
用于监听 RunLoop 单次循环的 6 个关键节点,是线上卡顿监控、性能优化的核心工具:
-
kCFRunLoopEntry:进入循环
-
kCFRunLoopBeforeTimers:即将处理定时器
-
kCFRunLoopBeforeSources:即将处理 Source0 事件
-
kCFRunLoopBeforeWaiting:线程即将休眠(卡顿监控核心节点)
-
kCFRunLoopAfterWaiting:线程被唤醒,结束休眠
-
kCFRunLoopExit:单次循环结束
RunLoop 内部运行流程

runLoop和多线程
