美文网首页
iOS面试 -- RunLoop

iOS面试 -- RunLoop

作者: 唐师兄 | 来源:发表于2020-03-21 20:06 被阅读0次

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

相关文章

网友评论

      本文标题:iOS面试 -- RunLoop

      本文链接:https://www.haomeiwen.com/subject/hwwqdhtx.html