《新浪微博剖析 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
- 观测时间点
kCFRunLoopEntry
kCFRunLoopBeforeTimers
kCFRunLoopBeforeSources
kCFRunLoopBeforeWaiting
(用户态切内核态)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