本文主要梳理iOS UI 核心知识
-
- UITableView 相关
-
- 事件传递&视图响应
-
- 图像显示原理
-
- 卡顿&掉帧原因方案
-
- 绘制原理&异步绘制
-
- 离屏渲染触发时机&为什么要避免离屏渲染
1.UITableView 相关
UITableView核心主要在于 重用机制和数据源同步
重用机制
如图列表会维持一个重用池子,当cell从列表消失的时候会放到重用池里边,后续使用如果重用池里边有直接取出来,否则重新alloc 创建。
数据源同步
对于多线程情况需要注意的是数据源同步的问题,一般在新闻,咨询类app中,主要考虑问题,如何在tableview解决多线程情况下,数据的处理。
并发访问,数据拷贝
对于并发访问,一般在子线程处理数据,如请求网络,在此之前需要先copy原始列表数据,当子线程处理完数据后,再copy回到主任务线程,刷新ui,保证数据完整性。
串行访问
对于串行访问,保证数据请求完成后,再去刷新ui。
2.事件传递&视图响应
事件传递
事件传递核心在于 事件的传递链和响应链
两个方法
-
(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { }
-
(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { }
事件传递从uiapplication->uiwindow->uiview
hitTest 返回命中的目标视图,最佳响应者,如果是uiview的子视图,会递归倒序遍历子视图里边的 hitTest(hitTest会判断 alpha > 0.1 ,userInteractionEnabled = true , opaque = 1),如果有命中,会通过pointInside 判断当前点击区域是否在视图内,如果在就响应事件, 通过 pointInside还可以自定义响应区域。
需要注意如果点击的一个子视图超出了父试图,那么传递链 在判断父试图的时候已经被中断,因为点击区域不在父试图里边,从而最终丢弃了事件传递。
视图响应
响应链从 first view -> super view -> ... -> view controller -> window -> Application -> AppDelegate
简单总结,事件链包含传递链和响应链,事件通过传递链传递上去,通过响应链找到相应的 UIResponse。
完整流程
主要有uiview和calayer
uiview 为calayer 提供内容,以及负责处理触摸等事件,参与响应链
calyer 负责显示内容 contents
符合单一职责模式
响应链顺序
是从当前最上层的view -> superview -> uiviewcontroller ->uiwindow ->uiapplication
继承关系
uibutton ->uicontrol->uiview ->uireponder
3.图像显示原理
通过cpu计算 gpu渲染 最终提交到帧缓冲区,通过视图控制器显示到屏幕上。
4.卡顿&掉帧原因
卡顿原因
在规定的16.7ms之内,下-帧VSync信号到来之前,并没有cpu和gpu共同完成下一帧画面的合成,于是就造成了卡顿和掉帧。
滑动优化方案
从cpu 和 gpu
cpu 1.对象创建,调整,销毁 2.预排班(布局计算,文本计算) 3.预渲染(文本等异步绘制,图片编解码等)
gpu 1.纹理渲染 2.视图混合
通用渲染流水线
应用阶段
几何阶段
光栅化阶段
像素处理阶段
5.绘制原理&异步绘制
[layer.delegate displayLayer:]
代理负责生成对应的bitmap ,设置该bitmap作为layer.contents属性的值
异步绘制: mp.weixin.qq.com/s?__biz=MzA…
6.离屏渲染触发时机&为什么要避免离屏渲染
当我们处理图层的属性在被指定为未被预合成之前不能直接在屏幕上显示,就触发了离屏渲染。离屏渲染的概念起源于gpu层面,指的是gpu在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。
何时触发
- 圆角
- 图层蒙版
- 阴影
- 光栏化
为何要避免
上下文切换,GPU额外的开销 创建新的渲染缓冲区,内存损耗 最优回答: 触发离屏渲染会增加GPU的工作量,而增加GPU的工作量很有可能导致GPU和CPU的工作总耗时超过了16.67ms,有可能导致UI的卡顿和掉帧。