
Runloop简介
  顾名思义,从命名上来讲就是一直在循环运行,按照API
文旦给的解释是用来处理输入源的,包括触摸、键盘和端口等信息,目的就是接收事件处理,没有就休息等待,想一个APP
程序启动之后就有一个对应的Runloop
在运行,下面摘抄官方解释(链接)
A NSRunLoop object processes input for sources such as mouse and keyboard events from the window system, NSPort objects, and NSConnection objects. A NSRunLoop object also processes NSTimer events.
不过注意NSRunLoop
是非线程安全的,只能被当前对应的线程进行操作,不要在其他线程调用任何改NSRunLoop
方法。也处理NSTimer
事件,虽然不是输入源,作为一种特殊的输入类型。
Runloop工作原理
  封面图展示的左边为工作过程,右边为内部结构组成。其中包括多组Mode
,每个Mode
又包含Source
、Observer
和Timer
,运行的时候只能在处于一个Mode
中,切换需要先退出当前运行Mode
再进入指定Mode
,下面看看Mode
这三个元素
1.Source
属于Set
类型,表示事件来源,又分为Source0
和Source1
:
- Source0,非基于Port,用于处理用户主动触发的事件,如屏幕触摸事件
- Source1,基于Port,处理内核相关的信息,如
IPC
就是基于这个处理的。也会分发一些给Source0
去处理
2.Observer
观察者,监听状态改变,监听的事件种类有
1 | /* Run Loop Observer Activities */ |
3.Timer
为定时器,在Runloop
运行的时候会进行计时,然后唤醒指定的操作。
Runloop工作流程图如下:

简单来讲就是一个do-while
循环,有输入源就唤醒,没有就处于休眠状态,官方解释链接。具体过程如下:
- 通知观察者开始进入Runloop
- 通知观察者开始处理Timer事件
- 通知观察者将要处理非基于port的事件
- 启动准备好的事件
- 如果基于port的事件已经准备好,立即启动。并进入步骤9
- 通知观察者进入休眠状态
- 线程进入休眠直到以下事件出现
- 基于port的事件源出现
- 定时器启动
- 设置的时间已经超时
- RunLoop被唤醒
- 通知观察者线程将被唤醒
- 处理已经进入的事件
- 如果用户自定义的计时器启动,处理事件并重启Runloop。转到第二步
- 输入源启动,传递消息
- 如果Runloop被显示唤醒且没有超时,重启Runloop。转到第二步
- 通知观察者Runloop已经推出
Runloop应用场景
常见的就是需要线程常驻功能,这也是Runloop
存在的意义,保证不退出且不消耗资源。