《新浪微博剖析 iOS 高级面试》笔记(七):RunLoop相关面试问题
概念
Runloop是通过内部维护的事件循环来对事件/消息进行管理的一个对象。事件循环就是没有消息需要处理时,休眠以避免资源占用。用户态切换到内核态。
- 有消息需要处理时,立刻被唤醒。
内核态切换到用户态。
1、main函数为什么可以保证不退出?
UIApplicationMain启动主线程的runloop
数据结构
- CFRunLoop
- pthread
runloop和线程是一一对应的
- currentMode
CFRunLoopMode
- modes
NSMutableSet<CFRunLoopMode *>
- commonModes
NSMutableSet<NSString *>
- commonModelItems
NSMutableSet<<Observer, Timer, Source>>
- pthread
- CFRunLoopMode
- name
NSDefaultRunLoopMode
- sources0
NSMutableSet
- sources1
NSMutableSet
- observers
NSMutableArray
- timers
NSMutableArray
- name
- Source/Timer/Observer
- Source0
- 当添加事件到
Source0,它并不会主动唤醒线程,需要手动唤醒线程。
- 当添加事件到
- Source1
- 具备唤醒线程的能力。
- CFRunLoopTimer
- 基于事件的定时器,和
NSTimer是可以转换的。
- 基于事件的定时器,和
- CFRunLoopObserver
- 观测时间点
kCFRunLoopEntrykCFRunLoopBeforeTimerskCFRunLoopBeforeSourceskCFRunLoopBeforeWaiting(用户态切内核态)kCFRunLoopAfterWaiting(内核态切用户态)kCFRunLoopExit
- 观测时间点
- Source0
1、各个数据结构之间的关系

- 当在
mode1下运行时,只能接收和处理mode1下的sources、observers、timers,是无法接收mode2、mode3下的事件回调的。
2、如何将一个Timer同时加入到两个Mode中?

commonMode不是实际存在的一种Mode。- 是同步
Source/Timer/Observer到多个Mode中的一种技术方案。
事件循环机制
1、RunLoop事件循环机制是什么样的?

2、如何唤醒休眠的Runloop?
- Source1
- Timer事件
- 外部手动唤醒
RunLoop与NSTimer
1、滑动TableView的时候定时器还会生效吗?
- 在滑动时,
currentMode会从kCFRunLoopDefaultMode切换到UITrackingRunLoopMode。 - 可以通过
CFRunLoopAddTimer(runLoop,timer,commonMode)函数,将timer添加到commonMode当中。 commonMode的作用就是将某一个事件源同步到多个mode当中。
RunLoop与多线程
线程和RunLoop是一一对应的。- 自己创建的
线程默认是没有RunLoop的。
1、怎样实现一个常驻线程?
- 为当前线程开启一个
RunLoop。 - 向该
RunLoop中添加一个Port/Source等维持RunLoop的事件循环。 - 启动该
RunLoop。
RunLoop面试总结
- 什么是
RunLoop,它是怎样做到有事做事,没事休息的? RunLoop与线程是怎样的关系?- 如何实现一个
常驻线程? - 怎样保证子线程数据回来更新
UI的时候不打断用户的滑动操作?- 把
子线程抛回给主线程更新UI的逻辑,包装起来,提交到主线程的kCFRunLoopDefaultMode下。 - 当前用户滑动
tableView处于UITrackingRunLoopMode模式下就不会执行该逻辑。 - 当用户停止滑动之后,当前线程
mode切换到kCFRunLoopDefaultMode下,就会处理更新UI的逻辑。
- 把
转载自:https://juejin.cn/post/6901585839952756744