一、初识 RunLoop(整体概念)
1. 什么是 RunLoop?
- 顾名思义:运行循环
- 在程序
运行
过程中循环
做一些事情
2. RunLoop 的应用范畴
- 定时器(NSTimer)、 PerformSelector
- GCD Async Main Queue
- 事件响应、手势识别、页面刷新
- 网络请求
- AutoReleasePool
3. 没有 RunLoop 会怎么样?
- 程序运行完 19 行代码后,会立即退出程序。
4. 有 RunLoop 会怎么样?
二、 RunLoop 的一些基本概念
1. RunLoop 对象
- iOS 中有 2 套 API 来访问和使用
RunLoop
- Foundation 框架:
NSRunLoop
- Core Foundation 框架:
CFRunLoopRef
-
NSRunLoop
是基于CFRunLoopRef
的一层 OC 包装 -
CFRunLoopRef
是开源的 - https://opensource.apple.com/tarballs/CF/
2. RunLoop 和线程的关系
- 每条
线程
都有唯一一个
与之对应的RunLoop
对象 -
RunLoop
保存在一个全局的Dictionary
里面,线程作为key
,RunLoop
作为value
- 线程刚刚创建时,并没有
RunLoop
对象,RunLoop
会在第一次获取
它时创建 -
RunLoop
会在线程结束时销毁 - 主线程的
RunLoop
已经自动获取
(创建),子线程默认没有开启RunLoop
3. RunLoop 相关的类
4. CFRunLoopModeRef 相关的介绍
-
CFRunLoopModeRel
代表RunLoop
的运行模式 - 一个
RunLoop
包含若干个Mode
,每个Mode
又包含若干个Source0/Source1/Timer/Observer
-
RunLoop
启动时只能选择其中一个Mode
,作为currentMode
-
不同组
的Source0/Source1/Timer/Observer
能分隔开来,互不影响 - 如果启动时
Mode
里面没有任何Source0/Source1/Timer/Observer
,RunLoop
会立马退出
5. 常见的两种 mode
-
kCFRunLoopDefaultMode(NSDefaultRunLoopMode)
:App的默认Mode
,通常主线程就是在这个Mode
下运行的 -
UITrackingRunLoopMode
:界面跟踪Mode
,用于ScrollView
追踪触摸滑动,保证界面滑动时不受其他Mode
影响 -
kCFRunLoopCommonModes
:默认包括kCFRunLoopDefaultMode
和UITrackingRunLoopMode
三、 代码中查看 RunLoop
1. 查看 touchesBegan:withEvent:
函数调用栈
- 我们从函数调用栈中看到
source0
的相关信息,这是因为source0
就是和触摸事件处理相关
2. 思考 CFRunLoopRef runloopRef = CFRunLoopGetMain();
和 NSRunLoop *runloop = [NSRunLoop mainRunLoop];
的内存地址相同吗?不是说一个线程只有一个 RunLoop 吗?为什么会不相同呢?
- 两种方式获得的 RunLoop 对象内存地址不相同
- NSRunLoop 是对 CFRunLoopRef 的一种包装,所以内存地址不相同,本质是一样的,我们从图中的红框看到,NSRunLoop 里面的实际地址和 CFRunLoopRef 是一致的。