一、 RunLoop
通过内部维护事件循环来对事件/消息进行管理的一个对象。
没有消息处理时,进入休眠以避免资源占用
有消息时,立刻被唤醒
1.1 事件循环(Event Loop)
事件循环对消息进行管理,管理状态的切换
没有消息时: 用户态 ----> 内核态
有消息时:用户态 <---- 内核态
1.2 main函数为什么不会退出?
因为调用UIApplicationMain启动了一个Runloop。有接收消息进行处理,没有消息进入等待。
二、 数据结构
NSRunLoop是CFRunLoop的封装,提供面向对象的API。
- CFRunLoop
- CFRunLoopMode
- Source/Timer/Observer
2.1 CFRunLoop
包含的内容:
- pthread : 与线程相关,一一对应。
- currentMode
- modes 集合NSMutableSet<CFRunLoop *>
- commonModes: NSMutableSet<String *>
- commonModeItems: 集合,包含多个Observer、Timer、Source。
2.2 CFRunLoopMode
RunLoopMode中包含的内容:
- name: 名称NSDefaultRunLoopMode
- source0
- source1
- observers 数组
- timers 数组
一个Mode对应多个Source/Timer/Observer。RunLoop只能接受到当前Mode中添加的事件。
NSRunLoopCommonMode不是实际存在的Mode。是同步Source/Timer/Observer到多个Mode中的一种技术方案。
2.3 CFRunLoopSource
- source0: 手动唤醒线程。
- source1 :自动唤醒线程
2.4 CFRunLoopTimer
基于事件的定时器,可以与NSTimer进行转换。
2.5 CFRunLoopObserver
观测时间点:
- kCFRunLoopEntry 进入RunLoop
- kCFRunLoopBeforeTimers 将要处理Timer事件
- kCFRunLoopBeforeSources 将要处理Source事件
- kCFRunLoopBeforeWaiting 将要进入休眠状态,切换用户态--->内核态。
- kCFRunLoopAfterWaiting 唤醒,内核态--->用户态
- kCFRunLoopExit 退出
2.6 各个数据结构之间的关系
一个RunLoop对应多个Model,一个Model对应多个Source/Timer/Observer。
三、事件循环的实现机制
image.png四、RunLoop与NSTimer
滑动TableView的时候定时器为什么会失效?
因为滑动TableView的时候,RunLoop发生了Mode切换。
kCFRunLoopDefaultMode ---> UITrackingRunLoopMode。
解决方法:将NSTimer添加到多个Mode中。
五、RunLoop和多线程关系
如何实现常驻线程?
- 为当前线程开启一个RunLoop。
- 向该RunLoop中添加一个Port/Source等维持RunLoop的事件循环。
- 启动该RunLoop。
小结
什么是RunLoop? 他怎么有事做事没事休息的?
RunLoop和线程的关系?
如何实现一个常驻线程?
本文并没有深入研究RunLoop,只是梳理RunLoop相关的知识点。如果想深入学习推荐《小马哥底层课程》。
网友评论