最近看了很多关于IOS优化的文章,现在大概来总结一下.
列表优化:
卡顿产生的原因
首先我们要了解优化任务的底层运行原理是什么,因为只有了解了运行原理。才可以知道着手从哪里优化。事半功倍。
我们知道iOS设备大部分情况下,屏幕刷新频率是60hz,每隔16.67ms会进行一次屏幕刷新。每次刷新时,需要CPU和GPU配合完成一次图像显示。其主要流程如下:
1.CPU创建View 设置其属性(frame, background,color等)
2.创建backImages setContents将image传给layer,或者通过draw绘制图形。
3.准备。core animation将layer发送到 render server前的一些准备工作,比如图片解码等
4.提交 coreanimation将layers打包通过ipc发送到render server
render server:
设置用来渲染的OpenGL triangles 如果有动画,还需要计算动画的参数
渲染这些可见的triangles 将结果提交到视频缓冲区
视图控制器以60hz品读读取缓冲区内容显示到显示器,如果在16.67ms内没有完成提交,则会被丢弃。
得出的结论就是,无论是GPU还是CPU都有各自的任务,无论哪个压力过大,都会造成卡顿。
通过instrument等测试工具可以发现,tableview在滑动过程中,cpu占用率高,而在空闲的时候 cpu占用率低。
主线程cpu占用率高,子线程cpu占用率低
解决方案
预加载:
滑动时CPU占用过高,16.67ms内无法完成内容提交—>导致卡顿
滑动时CPU占用率高,但空闲时CPU占用率底—>CPU占用分布特点
利用CPU空闲时间预加载,降低滑动时CPU占用峰值—>解决卡顿
如何预加载:
创建列表前找时机预加载。如启动时候,viewDidLoad runloop空闲时等
加载内容:列表将要滑动的时候会加载到的本地缓存图片等,需要耗时的资源。
动态预加载:
在IOS10以后,UITableView和UICollectionView提供了预加载机制,IOS12开始prefeatching做了优化,不再是和cell同时并发进行,而是cell加载完成之后串行开始prefeatch,从而优化了流畅度。
在IOS10以前我们可以用UIScrollview的代理方法进行预加载的操作
加载内容:
cell的高度, subView的布局计算。(cell少用autolayout)
拉取网络数据
网络图片
其他耗时的资源
线程优化
为什么要用多线程:
因为在IOS中,UIKit大部分的API都需要在主线程中调用,特别是一些耗时的操作,如view的创建,布局和渲染默认都是在主线程上完成的。如果主线程的任务过多,就会影响到开发的效率,造成卡顿。将非主线程必须的任务,移到子线程中,减轻主线程的负担。
推荐在子线程中进行的任务:
1.图片解码
2.文本渲染 UILabel和UITextView都是在主线程渲染的,当显示大量文本的时候 CPU的压力会非常大 用TextKit或最底层的CoreText对文本异步绘制。它的优势非常大,CoreText对象创建好后,能直接获取文本的宽高等信息,避免了多次计算。
缓存:
缓存的内容可以是
UIView,view的创建代价很大,一些可以服用的view可以cache,例如UITableView为我们实现的cell的服用。
图片,图片涉及磁盘IO和解码,十分耗时,可以考虑缓存。
布