美文网首页
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