第十篇:Objective-C 知识回顾RunLoop
2019-11-22 本文已影响0人
望穿秋水小作坊
RunLoop 大纲
10.1.RunLoop 的概念
问题一:请用你对 RunLoop 的理解,描述一下什么是 RunLoop?
- RunLoop 是通过内部维护的 事件循环 来对 事件/消息进行管理 的一个对象
问题二:RunLoop 内部的事件循环是怎么样的呢?
- 没有消息需要处理时,休眠以避免资源占用
- 有消息需要处理时,立刻被唤醒
- 在 main 函数内部会调用 UIApplicationMain 的函数内部会启动主线程的 RunLoop。
- 而 RunLoop 是对事件循环的一种维护机制,可以做到有事件的时候即使唤醒从内核态到用户态,没有事件处理的时候会进行休眠从用户态进入内核态。从而避免资源的占用。
10.2.RunLoop 相关数据结构
- NSRunLoop 是 CFRunLoop的封装,提供了面向对象的 API
- CFRunloop
-CFRunLoopMode - Source/Timer/Observer
问题一: tableView 滚动的时候,NSTimer 还会生效吗?
- 我们创建的
NSTimer
默认是添加到RunLoop
的NSDefaultRunLoopMode
模式下。(苹果这么做也是为了节约资源) -
TableView
滚动的时候,会让RunLoop 从 NSDefaultRunLoopMode
切换到UITrackingRunLoopMode
,我们的定时器就不会生效了。 - 解决方法
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]]
将定时器添加进去。
问题二:CommonMode 的特殊性?
- CommonMode
不是实际存在的
一种 Mode。 - 是同步 Source/Timer/Observer 到多个 Mode 中的
一种技术方案
。
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 更新了。