runloop面试题

146 阅读2分钟

runloop和多线程的关系

  • runloop与线程是一一对应的关系,并且保存在一个全局的字典中,runloop会在线程中第一次获取runloop的时候创建。

runloop中的类

  • runloop有model,source,observe,timer
  • runloop中有若干个model,对应有一个currentmodel。model中有若干个Source,observe,timer。这么做主要是为了隔离Source,observer,timer事件,提升交互流畅。
  • Source,observer,timer组合成为modelItems

runloop中model

  • 可用的是defaultmodel和trakingmodel,commonmodel是提供一个标记,加入到common的集合中,runloop在default和traking模式下都回去调用这个集合中的modelitem

source

  • runloop中的source1接受系统事件,首先由 IOKit.framework 生成一个 IOHIDEvent 事件并由 SpringBoard 接收。SpringBoard 只接收按键(锁屏/静音等),触摸,加速,接近传感器等几种 Event,随后用 mach port 转发给需要的App进程。随后苹果注册的那个 Source1 就会触发回调,并调用 _UIApplicationHandleEventQueue() 进行应用内部的分发,Source0接收Event事件,往下传递,进行响应链处理

observe

可以注册一个observe去监听runloop的整个过程,

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry         = (1UL << 0), // 即将进入Loop
    kCFRunLoopBeforeTimers  = (1UL << 1), // 即将处理 Timer
    kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
    kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
    kCFRunLoopAfterWaiting  = (1UL << 6), // 刚从休眠中唤醒
    kCFRunLoopExit          = (1UL << 7), // 即将退出Loop
};

NSTimer

NSTimer 其实就是 CFRunLoopTimerRef,他们之间是 toll-free bridged 的。一个 NSTimer 注册到 RunLoop 后,RunLoop 会为其重复的时间点注册好事件。例如 10:00, 10:10, 10:20 这几个时间点。RunLoop为了节省资源,并不会在非常准确的时间点回调这个Timer。Timer 有个属性叫做 Tolerance (宽容度),标示了当时间点到后,容许有多少最大误差

参考链接:runloop详解