1. RunLoop 概念
在iOS中一个app只能开启一个进程,然后又一个主线程,可以开辟多个线程,一个线程一次只能执行一个任务,执行完之后,对应的线程就会退出
当我们需要一个常驻线程,可以让线程在需要做事的时候忙起来,不需要的话就让线程休眠,可以这样做:
do {
//获取消息
//处理消息
} while (消息 != 退出)
上面的这种循环模型被称作 Event Loop。Event Loop 在很多系统和框架里都有实现,如 Windows 程序的消息循环、OSX/iOS 里的 RunLoop
OSX/iOS 系统中,提供了两个这样的对象: NSRunLoop 和 CFRunLoopRef
![](https://img.haomeiwen.com/i843495/2f5c3ebcc4197ec6.png)
- CFRunLoopRef 是在 CoreFoundation 框架内的,它提供了纯 C 函数的 API,所有这些 API 都是线程安全的
- NSRunLoop 是基于 CFRunLoopRef 的封装,提供了面向对象的 API,但是这些 API 不是线程安全的
2. RunLoop 基本作用
- 使程序一直运行并接受用户输入 程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不会被销毁,也就保证了程序的持续运行
- 决定程序在何时应该处理哪些Event 比如:触摸事件,定时器事件,Selector事件等
- 节省CPU时间 程序运行起来时,什么操作都没有做的时候,RunLoop就告诉CPU,现在没有事情做,我要去休息,这时CPU就会将其资源释放出来去做其他的事情,当有事情做的时候RunLoop就会立马起来去做事情
3. RunLoop 与 线程
苹果不允许直接创建RunLoop,但是可以通过[NSRunLoop currentRunLoop]或者CFRunLoopGetCurrent()来获取(如果没有就会自动创建一个)
线程和 RunLoop 之间是一一对应的,其关系是保存在一个 Dictionary 里。所以我们创建子线程RunLoop时,只需在子线程中获取当前线程的RunLoop对象即可[NSRunLoop currentRunLoop];如果不获取,那子线程就不会创建与之相关联的RunLoop,并且只能在一个线程的内部获取其 RunLoop
[NSRunLoop currentRunLoop];方法调用时,会先看一下字典里有没有存子线程相对用的RunLoop,如果有则直接返回RunLoop,如果没有则会创建一个,并将与之对应的子线程存入字典中。当线程结束时,RunLoop会被销毁
⚠️ 线程和 RunLoop 之间是一一对应的;其关系保存在一个全局的 Dictionary 里,线程作为key,RunLoop作为value;线程创建之后是没有RunLoop的(主线程除外);RunLoop在第一次获取时创建,在线程结束时销毁
4. RunLoop 组成
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
![](https://img.haomeiwen.com/i843495/d06475d00e2f04b7.png)
一个 RunLoop 包含若干个 Mode,每个 Mode 又包含若干个 Source/Timer/Observer。每次调用 RunLoop 的主函数时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode。如果需要切换 Mode,只能退出 RunLoop,再重新指定一个 Mode 进入。这样做主要是为了分隔开不同组的 Source/Timer/Observer,让其互不影响
网友评论