第十篇:Objective-C 知识回顾RunLoop

RunLoop 大纲

10.1.RunLoop 的概念

问题一:请用你对 RunLoop 的理解,描述一下什么是 RunLoop?
  • RunLoop 是通过内部维护的 事件循环 来对 事件/消息进行管理 的一个对象
问题二:RunLoop 内部的事件循环是怎么样的呢?
  • 没有消息需要处理时,休眠以避免资源占用
  • 有消息需要处理时,立刻被唤醒
事件循环
main 函数为什么不会退出呢?
  • 在 main 函数内部会调用 UIApplicationMain 的函数内部会启动主线程的 RunLoop。
  • 而 RunLoop 是对事件循环的一种维护机制,可以做到有事件的时候即使唤醒从内核态到用户态,没有事件处理的时候会进行休眠从用户态进入内核态。从而避免资源的占用。

10.2.RunLoop 相关数据结构

  • NSRunLoop 是 CFRunLoop的封装,提供了面向对象的 API
  • CFRunloop
    -CFRunLoopMode
  • Source/Timer/Observer
结构关系
问题一: tableView 滚动的时候,NSTimer 还会生效吗?
  • 我们创建的NSTimer默认是添加到RunLoopNSDefaultRunLoopMode模式下。(苹果这么做也是为了节约资源)
  • TableView 滚动的时候,会让 RunLoop 从 NSDefaultRunLoopMode 切换到 UITrackingRunLoopMode,我们的定时器就不会生效了。
  • 解决方法 [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]] 将定时器添加进去。
问题二:CommonMode 的特殊性?
  • CommonMode 不是实际存在的一种 Mode。
  • 是同步 Source/Timer/Observer 到多个 Mode 中的一种技术方案
整个 runloop 的时间循环机制

10.3.RunLoop 与 多线程

  • 线程和 RunLoop 是一一对应的。
  • 自己创建的线程,默认是没有 RunLoop 的。
问题一:怎么样实现一个常驻线程呢?
  • 为当前线程开启一个 RunLoop。(其实是调用[NSRunLoop currentRunLoop]苹果使用懒加载方式,只要调用获取方式,没有的对应线程 RunLoop 的情况会为当前线程创建一个 RunLoop)
  • 向该 RunLoop 中添加一个 Port/Source 等维持 RunLoop 的事件循环。
  • 启动该 RunLoop。(需要先添加事件因子,不然没有事情做的 RunLoop 启动后会离开关闭退出)
问题二:怎么样保证子线程数据回来更新 UI 的时候,不打断用户的滑动操作。
  • 可以把子线程回来的数据,需要进行更新的 UI 打包的 RunLoop 的 KCFRunLoopDefaultMode 模式下。
  • 此时用户滑动,RunLoop 处于 UITrackingRunLoopMode模式,不会对 KCFRunLoopDefaultMode的事情进行处理,就不会打断用户的滑动操作。
  • 等用户滑动完毕,切换回 KCFRunLoopDefaultMode 模式的时候,就会进行 UI 更新了。

推荐阅读更多精彩内容