前言
很多iOS 开发,都会面临到解决开发过程中的卡顿问题,从而也衍生出来很多的方法去解决卡顿问题,这篇文章来描述下iOS卡顿产生的原因,以及一部分解决办法;
iOS卡顿原理
1.像素是如何显示到屏幕上
从最初的电子枪显示器说起,电子枪逐行读取像素点,逐行发射到屏幕上,每当一行扫描完成,显示器会发出水平同步信号HSync;然后继续下一行,直到最后一行完成一帧的绘制,电子枪恢复到起点继续下一帧的绘制,显示器会发出一个垂直同步信号VSync。对于iOS设备,VSync信号的间隔是16.7ms,也就是1秒60帧。
实际绘制过程中:
-
由CPU 计算好显示的内容:如视图的创建,布局的计算,图片的解码,文本的绘制,
-
然后GPU完成渲染,得到最终的像素,像素会输出到帧缓存(Frame Buffer)中
-
Video Controller (视频控制器)发出垂直信号(每16.67ms读取一次)进行读取Frame Buffer
-
最终输出到Monitor(显示器)上面。
假设只有一个Frame Buffer,意味着GPU和CPU必须在VSync发出的瞬间完成前面所有的工作,否则在视频控制器显示的过程中修改Frame Buffer,那么显示器就会在这一帧的前半部分显示上一帧的内容,下半部分显示当前帧的内容,造成画面断层的怪异现象。为了解决这个问题,大多数平台都引入了多缓存机制,比如iOS平台的双缓存, Android平台的三缓存机制;
因为苹果使用双缓冲区,根据上图,当垂直信号过来之后,但是GPU还没有渲染完成,就会出现掉帧(卡顿)显现;
卡顿监测
-
根据RunLoop从任务开始beforeSoure 到任务任务结束 beforeWating 如果时间过长 ,基本认为卡顿了
简易实现Demo 微信实现Demo <startBlockMonitor方法>
-
FPS:根据CADisplayLink 来查看 屏幕刷新频率保持一致 一般情况保持50—60就认为还是可以的
YYLabel实现Demo (demo中有对字符串渲染优化以及帧率监听)
卡顿优化
预排版
缓存tableView cell 的高度,在异步子线程中计算好布局,回到主线程,这里可能就要放弃autolayout 进行frame布局
预解码 & 预渲染
其中预渲染圆角问题,我们可以直接找UI切一个圆角蒙版
预解码 SDWebImage 或YYImage 中有是先用
RunLoop 按需加载加载需要的前3行 和后3行(这个缺点在于快速滑动会有白屏)
异步渲染
减少图层层级,使用core Graphic合成位图 使用Graver 进行合成操作 查看Demo
Graver的渲染流程
总结
以上就是对iOS中的卡顿原理,以及卡顿的一些解决方案
希望对大家有用处,欢迎大家点赞+评论,关注我的CSDN,我会定期做一些技术分享!未完待续。。。