UI视图相关
- UITableView
- 事件传递&视图响应
- 图像显示原理
- 卡顿&掉帧
- 绘制原理&异步绘制
- 离屏渲染
1. UITableView
- 重用机制
- 数据源同步(多线程)
重用机制
cell = [UITableView dequeueReusableCellWithIdentifier:@"identifier"];
- 不在屏幕上的cell 放到重用池中,即将在屏幕上显示的cell用相同的重用标识符从重用池中取得缓存的cell
数据源同步(UI刷新错乱)
- 并发访问,数据拷贝
- 串行访问
2. 事件传递&视图响应
- UIView和CALayer
- 事件传递与视图响应链
1. UIView和CALayer
- UIView显示的部分是CALayer的contents(backing store),UIView的backgroundColor是CALayer的同名属性的封装
- 区别
- UIView 为CALayer提供显示的内容,以及负责触摸灯事件,参与响应链(设计原则,单一职责原则)
- CALayer只负责内容contents的显示
2. 事件传递与视图响应链
涉及的两个方法
hitTest:withEvent:
(方法一)与pointInside:withEvent:
(方法二)-
流程:
- 用户点击了屏幕,硬件接收到点击事件后,由UIKit(硬件驱动)处理包装事件,发送给桌面,如果桌面当前没有程序在运行,就转换成自己的事件,如点击APP图标启动APP,滑动APP列表,或者打开通知中心等。如果有APP在前台运行,就把事件传给APP,APP会利用RunLoop处理事件。
- App会把事件分发给当前的UIWindow对象,UIWindow对象会调用方法一返回对应的视图。在调用方法一之前会判断当前视图不是是隐藏,用户交互是enable,透明度大于0.01,然后调用方法二,检测触摸点是否在本视图之内,如果不在则不进行方法一,如果在就会用倒叙的方法遍历自己的子视图,让他们走一遍方法二与方法一,如果子视图方法一返回的UIView不为空则让这个UIView处理点击事件,如果他不处理就让他的父视图处理,以此类推,最后都没有视图响应就丢弃。
-
事件响应
touchesBegan(Modved)(Ended):withEvent:
3. 图像显示原理
设计工作单位
- cpu
- gpu:涂层渲染,纹理合成
- 帧缓冲区:gpu产生的数据
- 视频控制器:把帧缓冲去的数据显示到显示器
- 显示器
UI具体显示
- CALayer(内容布局等计算)(cpu负责)
- Core Animation(cpu负责)
- OpenGL(ES)(GPU负责)
- Screen
cpu具体流程
- 布局计算(UI布局,文本计算)
- 显示计算(drawRect:)
- 其他一些准备工作(图片编解码)
- 提交内容给GPU(提交位图)
GPU渲染管线(OpenGL渲染管线)
- 顶点着色
- 图元装配
- 光栅化
- 片段着色
- 片段处理
- 把最终的像素点提交到帧缓冲区中(视频控制器会在VSync(垂直同步)到来时显示在屏幕上)
4. 卡顿&掉帧
- 原因
- 解决方案
1. 原因
- 16.7ms产生一帧画面
- cpu+gpu提交一次帧缓冲区的时间和小于16.7ms
- 时间大于这个时间 就会产生掉帧,卡顿现象
2. 解决方案
- 从cpu
- 对象的创建调整销毁(子线程)
- 预排版 (布局计算,文本计算)
- 预渲染(文本异步绘制,图片编码等)
- 从GPU
- 纹理渲染(离屏渲染)
- 视图混合(视图复杂,减轻视图复杂程度)
5. 绘制原理&异步绘制
- UIView对象调用
setNeedsDisplay
方法,就会调用他的layer的同名方法 - layer标记自己需要在runloop休眠时刷新自身contents-
[layer display]
- 在刷新自身content算的时候会判断自身的delegate是否响应了
displayLayer:
方法,如果没有就走系统绘制流程,如果有则走用户自定义的绘制流程(这也是异步绘制的突破点)
系统绘制流程
- CALayer 创建 backing store(CGContextRef)
- layer代理没有响应方法
- CALayer 调用
drawInContext:
- CALayer 上传backing store
- 结束
自定义绘制流程
这个过程要求代理自己生成响应的bitmap(位图),并且把bitmap设置为layer.contents的值。
- 会在相应代理方法后调用代理绘制方法
- CGBitmapContextCreate()
- CoreGraphic API
- CGBitmapContextCreateImage()
- 回调UIView 的
drawRect:
让用户做一些其他自定义的事情 - 上传backing store
6. 离屏渲染-Off-Screen rendering
- 相对应的On-Screen Rendering
- Off-Screen rendering
1. 相对应的On-Screen Rendering
在当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行
2. Off-Screen rendering
GPU在当前屏幕缓冲区以外新开辟的一个缓冲区进行渲染操作
触发条件
- 圆角与maskToBounds 一起设置
- 图层蒙版
- 阴影
- 光栅化
为什么避免
增加GPU工作量,导致GPU工作时间增长
- 新的渲染缓冲区
- 上下文的切换