聊聊 iOS 中的 RunLoop 考题 (中文版)
![](https://img.haomeiwen.com/i3037351/6055d495aac1b04d.jpeg)
Run Loop 是与进程相关的基础设施。Run Loop 是来协调待接受的事件、安排调度的,事件处理循环。Run Loop 的作用就是,有任务,开起进程,没任务,休眠进程。
翻译自苹果的 runloop 文档
上一段代码 ,与 NSRunLoop 和 NSThread 相关,
NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];
-(void) someMethod
{
NSLog(@"operation");
}
Run Loop 是处理 sockets 网络, ports 端口, files 文件 , keyboard 键盘 , mouse 鼠标 , timers 计时器 的机制的一层抽象。
NSThread 都有着专属的 Run Loop ,可以通过 currentRunLoop 方法访问。
一般是不需要直接访问 Run Loop 的。可以用网络相关的组件指定Run Loop , 处理 IO 输入输出。
等着输入源有数据 / 事件,给定线程的 Run Loop 就会让合适的输入处理函数处理有数据 / 事件,等待执行的输入源。
执行完后,Run Loop 会还原。如果有其他输入源的数据 / 事件, 该线程的 Run Loop 会处理;如果无, 该线程会进入休眠状态。
以上是抽象后的简单描述,省略了很多细节。
继续解释:
run loop 是不是只能在线程内部访问,执行?
是的。 NSRunLoop 不是线程安全的。所以只在跑这个 run loop 的线程的上下文中获取比较好。
来一个简单地给 run loop 添加事件的例子?
上 🌰 :
如果想要监听 port , 添加该 port 到 run loop 就可以了,这个 run loop 就会监听该 port 的活动,
- (void)addPort:(NSPort *)aPort forMode:(NSString *)mode
也可以直接给 run loop 添加计时器,
- (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode
Run Loop 会还原,什么意思?
每一次迭代中,run loop 会按照他的 mode ,处理所有的条件满足的事件。这个问题与 run loop 的 mode 相关,要看文档。
开线程的时候,Run Loop 没有被唤醒?
大多应用,主线程的 Run Loop 自动去跑。
人为开的线程,要去开启对应的 Run Loop ,响应传入的事件。
{
所以, 开线程,用 timer ,需要手动开启对应的 Run Loop
}
能不能在线程外,给线程的 Run Loop 添加事件?
什么意思哈?
不是给 Run Loop 添加事件。是在持有 Run Loop 的线程中,添加输入源,例如计时器事件源。该 Run Loop 就会监听事件源的活动。
输入的数据可以来自其他的线程 / 进程。处理输入的 Run Loop 是监听这些事件源的 Run Loop ,跑在线程上。
是不是,有时候可以用 Run Loop 堵塞线程一会?
是的。事件处理返回前, Run Loop 会驻留处理事件。任意 app 中,都会轻易发现这点。任意的IO操作中,例如点击按钮,加一个睡眠函数。方法完成了,主 Run Loop 就被阻塞了,整个 UI 都挂了。
任何的 Run Loop 中,都适用。
Run, RunLoop, Run! RunLoop , 跑起来
交互性的应用与命令行程序的区别,就是 RunLoop . 使用命令行程序, 先配参数开起,执行命令,就结束了。交互性的应用等待用户输入,给用户反馈,然后一直等。很多长周期的进程中,都有这种机制。举个经典的例子,服务端中的
while( 1 ){ select( ); }
...
CFRunLoop 中最重要的特性是 CFRunLoopModes , RunLoop 的模态。 RunLoop 处理 Run Loop Sources , Run Loop 的事件源。事件源登记在 Run Loop 的一到多个模态上。 Run Loop 必须在一个给定模态上跑。事件源新加了事件,只要当该事件源与Run Loop 当前的模态一致,Run Loop 才处理该事件。
Mode 分为不同的模式, Common, UITracking ... , 也是一种状态。 个人觉得,可以叫模态。
建议阅读 Run Loop 文档,https://developer.apple.com/documentation/foundation/nsrunloop
线程中 Run Loop 的应用,
说明: 为了有意思一些, 我采取了意译。
本文翻译自
-
Stack Over Flow Understanding NSRunLoop
-
苹果的 runloop 文档