UI视图相关点
一.UITableView的重用机制
二.数据源同步问题(增删改查)
1.并发访问、数据拷贝(删除的时候记录下来,子线程回来的数据再对删除的数据进行删除处理)
2.串行访问(使用GCD的串行队列,子线程数据处理放到串行队列,主线程删除某一行也放到串行队列)
三.事件传递与视图响应链
一.UIView和CALayer
1.UIView为其提供内容,以及负责处理触摸等事件,参与响应链;
2.CALayer负责显示内容Contents
二.事件传递流程
点击屏幕-->UIApplication-->UIWindow-->此时调用hitTest返回最终响应的视图
其中调用hitTest方法系统方法内部会调用pointInside的方法判断当前点击的point是否在UIWindow内
如果是就再遍历UIWindow的SubViews(遍历的方式是倒序)首先查找最后添加到UIWindow上的视图,
在每个SubViews都会调用hitTest方法,可以理解为递归调用,如果hitTest返回有值,那么就作为响应者;
hitTest方法内部实现
1.首先先判断当前视图的hidden && userInteractionEnabled && alpha > 0.01
2.调用pointInside判断点击的点是否在当前的视图内
3.以倒序方式遍历subViews,遍历的过程中会调用hitTest方法,假如说有返回的view那这个view就作为响应,否则就继续遍历,直到遍历完;
视图传递链是相反方向,从顶层的view到UIWindow
图像显示原理
1.CPU GPU通过总线连接起来的,CPU中生成的位图在合适的时机通过总线上传给GPU
2.GPU拿到位图之后会对位图做相应的处理,包括图层是渲染 纹理的合成,之后放到帧缓冲区Frame Buff
3.由视频控制器根据信号在指定时间之前去提取帧缓冲区提取要显示的内容
UIView.CALayer.content属性,系统会在合适的时机内调用drawRect方法,位图绘制的内容通过CoreAnimation
然后提交给OpenGL(ES)进行最终的渲染,包括纹理的合成之后显示在屏幕上
CPU的工作:Layout UI布局 Display显示绘制 Prepare做一些准备工作 Commit通过总线提交给GPU
GPU的工作:顶点着色 图元装配 光栅化片段着色 片段处理
UI卡顿、掉帧的原因
1.一般流畅性是60pfs 指的是每一秒有60帧的画面 所以16.7ms要生成一帧;
2.16.7ms内需要CPU 跟GPU在这限定的时间内完成工作,如果CPU花的时间过长,那留给GPU的时间不多导致GPU工作还没完成时,下一个Vsync信号到来就直接去缓冲区取,这就导致卡顿或者说掉帧
滑动优化方案
1.CPU :对象的创建 调整 销毁 放到子线程中; 预排板(布局计算、文本计算);预渲染(文本等异步绘制,图片编解码等);
2.GPU:纹理渲染;视图混合
UIView绘制原理
1.UIView 调用setNeedsDisplay方法后并没有立即去绘制,系统会先调用view.layer 的 setNeedDisplay方法 之后相当于在此layer上打上标记 然后在当前的runloop结束之后才调用CALayrer 的display方法 在CALayer的display的内部方法中,首先会尝试layer.delegate能不能响应displayLayer:方法 假如说不响应就进入系统的绘制中,如果说响应的话实际上就给我们留有异步绘制入口的余地;
系统的绘制流程 CALayer会创建backing store(CGContextRef)然后看有没有代理,没有的话调用CALayer drawInContext 有的话就调用layer.delegate drawLayer:InContext:然后在合适时机调用UIView drawRect方法 然后不管哪种分支再由CALayer上传backing store到GPU
异步绘制
1.layer.delegate displayLayer 】进入异步绘制过程;代理负责生成对应的bitmap位图;设置该bitmap作为layer.contents属性的值;
AsynDrawingView setNeedsDisplay
CALayer display
AsyncDrawingView displayLayer
以上步骤是发生在主线程
CGBitmapContextCreate()
CoreGraphic API
CGBitmapContextCreateImage()
以上是子线程,之后 CALayer setContents
离屏渲染
在屏渲染:意思是当前的屏幕渲染,指的是GPU的渲染操作在当前用于显示屏幕缓冲区中进行
离屏渲染:指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作;通俗的说当我们设置某一些UI视图的图层属性 标记了它在未愈合之前不能用于当前屏幕上直接显示的时候触发离屏渲染;
离屏渲染何时触发?
1.圆角(当和maskToBounds一起使用的时候)
2.图层蒙版
3.阴影
4光栅化
为何要避免离屏渲染?
因为离屏渲染创建了新的渲染缓冲区;上下文切换
触发离屏渲染的增加了GPU的工作量,假如说跟CPU工作的总耗时加起来超过16.7ms的时候就会掉帧或者卡顿