1. 什么是 RunLoop?
通过系统内部维护的事件循环进行事件/消息管理的一个对象就是 runloop
特点:
- 没有消息需要处理时,休眠避免资源占用
状态切换: 用户态->内核态,有消息处理时,就是用户态的消息处理,而没有消息时,就托管到系统内核本身进行处理 - 有消息需要处理时,立刻被唤醒
状态切换:内核态->用户态
用户态:应用程序一般是运行在用户态
内核态:当我们发生系统调用的时候则是在内核态
为什么有用户态和内核态?
是因为计算机为了更好的进行资源分配以及调度,而使系统达到最佳的资源利用,故产生了用户态和内核态
为什么 main 函数能够保持一直存在且不退出?
在 main 函数内部会调用 UIApplicationMain 这样一个函数,而在UIApplicationMain内部会启动主线程的 runloop,因为 runloop 就是通过系统内部维护的事件循环进行事件/消息管理的一个对象,因为可以做到有消息处理时,能够迅速从内核态到用户态的切换,立刻唤醒处理,而没有消息处理时通过用户态到内核态的切换进入等待状态,避免资源占用。因此 main 函数能够一直存在且不退出。
在 OC中系统为我们提供了哪几种 runloop?
NSRunloop(Foundation),CFRunloop(CoreFoundation)
CFRunloop 的数据结构
- CFRunloop
- CFRunloopMode
- Source/Timer/Observer
CFRunloop
- pthread
- currentMode
- modes
- commonModes
- commonModeItems
pthread
- 代表线程,线程和 runloop 是一一对应的
currentMode - CFRunloopMode
modes - 表示的是一个CFRunloopMode的集合
commonModes - 也是一个集合,只是它是一个String 的集合
commonModeItems
- 也是一个集合,里面包含多个 source,多个 timer,多个 observer
CFRunloopMode
- name 当前 mode的名称
- sources0 集合
- sources1 集合
- observers 数组
- timers 数组
CFRunloopSource
- source0 需要手动唤醒线程
- source1 具备主动唤醒线程的能力
CFRunloopTimer
和 NSTimer 是可以免费桥接的
CFRunloopObserver
- 观测时间点
- kCFRunloopEntry
- kCFRunloopBeforeTimers
- kCFRunloopBeforeSources
- kCFRunloopBeforeWaiting (通知对应观察者当前 runloop 将要进入休眠状态了,系统将从用户态切换到内核态)
- kCFRunloopAfterWaiting
- kCFRunloopExit
runloop 和 model 以及 source 、 timer、observer 的关系?
如图,这是一个一对多的关系
runloop 的 mode
如图,runloop 中可以存在多个 mode,每个 mode中有多个 source,observe以及多个 timers,当我们的 runloop 运行在某个 mode中时, 是相互独立且互不干扰的,当 mode2 中的runloop 接收到回到时,我们运行在 mode 中的 runloop 是不能响应的。
滑动 tableView 的时候,timer 定时器失效了,为什么?
因为 UITableView 的 runloop 默认情况下是运行在 kCFRunloopDefaultMode中,当我们滑动的时候mode切换到UITrackingRunloopMode 中的,而定时器也是运行在 kCFRunloopDefaultMode 中,对应的 observer、timer是没有办法进行处理的,所以 timer 会失效,如何解决呢。可以通过 CFRunloopAddTimer函数把 timer 的 runloop 添加到 commonrunloopmode中,CFRunloopCurrentModes 是系统提供一个将当前 runloopmode添加到多个 mode 的方法,这不是一个真正意义存在的 mode,他是同步 source、observer、timer 到多个 mode 的一种技术解决方案,当我们调用CFRunloopAddTimer的时候,系统是会把我们创建的timer同步到UITrackingRunloopMode中的 timers 里面,因此当 tabview 滑动的时候,发生 mode 的切换,我们的 timer 依旧可以生效。
当一个休眠状态的 runloop 我们可以通过哪些方式唤醒?
- timer事件
- source1
- 外部手动唤醒
runloop 事件循环机制内部流程
怎么样实现一个常驻线程?(三步走)
- 为当前线程添加一个 runloop
- 向添加的 runloop添加一个 port/source 等维持 runloop 的事件循环
- 启动 runloop
网友评论