成像过程:
- 在iOS中是双缓冲机制,有前帧缓存、后帧缓存
成像原理:
- 发出垂直同步信号,告诉屏幕即将显示一帧数据;
- 发出水平同步信号,显示一行一行的数据,直到填充到整个屏幕为止。
产生卡顿的原因
- 如图:垂直同步信号的发射频率是固定的,信号发出,代表着即将显示数据;
- 如果期间,CPU或GPU有一步耗时较长(第3帧的渲染),垂直信号已发出,但是GPU还没有渲染完,那么就是显示渲染好的第2帧数据,连续显示相同的帧,就造成了画面卡顿。
- 第3帧会在第4次同步信号过来时再显示。
所以解决卡顿的主要思路:
- 尽可能减少CPU、GPU的资源消耗。(保证刷帧率60FPS.)
CPU优化:
-
尽量用轻量级的对象,比如用不到事件处理的地方,可以考虑使用CALayer取代UIView;
-
不要频繁地调用UIView的相关属性,比如frame、bounds、transform等属性,尽量减少不必要的修改;
-
尽量提前计算好布局,在有需要时一次性调整对应的属性,不要多次修改属性;
-
Autolayout会比直接设置frame消耗更多的CPU资源;
-
图片的size最好刚好跟UIImageView的size保持一致;
-
控制一下线程的最大并发数量;
-
尽量把耗时的操作放到子线程:
- 图片处理(解码、绘制);
- 文本处理(尺寸计算、绘制):
// 文字计算
[@"text" boundingRectWithSize:CGSizeMake(100, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:nil context:nil];
// 文字绘制
[@"text" drawWithRect:CGRectMake(0, 0, 100, 100) options:NSStringDrawingUsesLineFragmentOrigin attributes:nil context:nil];
GPU优化:
-
尽量避免短时间内大量图片的显示,尽可能将多张图片合成一张进行显示;
-
GPU能处理的最大纹理尺寸是4096x4096,一旦超过这个尺寸,就会占用CPU资源进行处理,所以纹理尽量不要超过这个尺寸;
-
尽量减少视图数量和层次;
-
减少透明的视图(alpha<1),不透明的就设置opaque为YES;
卡顿检测
思路:
-
平时所说的“卡顿”主要是因为在主线程执行了比较耗时的操作;
-
可以添加Observer到主线程RunLoop中,通过监听RunLoop状态切换的耗时,以达到监控卡顿的目的。
-
第三方:LXDAppMonitor