UITableView性能优化

ps:以下是我自己的学习笔记,有不对之处敬请指出,大家一起学习,一起进步!

前言:

做过iOS开发的程序猿iOS,不管是刚入门的初级iOS开发工程师,又或者是高级开发工程师都知道,UITableView是我们日常开发中使用频率最高的一个UIKit框架里边的控件,几乎所有的主流APP,甚至iPhone手机自带的软件都能看到它的身影。因此,关于UItableView的话题也很多,比如:UITableView用于显示时候性能问题,有时候会出现卡顿,或者掉帧的情况。今天就针对这一点进行学习总结,新手学习笔记,过于片面,敬请担待。

思考:

废话不多说进入主题。假入我们遇到这样的问题,应该从哪些方面去思考这个问题?哪些因素可能会导致出现这个问题?我们又应该怎么去解决?
当然可能由于我们自己的设计有问题,比如:tableview上有很多控件,设计很复杂。这种情况应该尽量避免。当然还有些是我们不可避免的,也是以下详细介绍的,我们都知道,界面上显示的东西都是GPU来完成的,而数据计算是CPU来完成的,所以界面卡顿可能是因为GPU,或者CPU的负载太大,导致卡顿。

分析:

假如tableview滑动比较快,且内部控件比较复杂会导致CPU的计算量过大,从而导致掉帧。因为GPU 一个机制叫做垂直同步(简写也是 V-Sync),当开启垂直同步后,GPU 会等待显示器的 VSync 信号发出后,才进行新的一帧渲染和缓冲区更新。这样能解决画面撕裂现象,也增加了画面流畅度,但需要消费更多的计算资源,也会带来部分延迟。当GPU发出垂直同步即VSync信号后,CPU开始进行内部控件的创建、布局、解码和控件的相对位置计算。然后将计算好的内容交给GPU进行变换、合成、渲染。然后等待下一个VSync信号。(这段理论部分来自于YY大神)假如在VSync信号发出后,CPU进行计算的时间过长,或者GPU进行渲染的时间过长导致两段时间加起来超过了1个VSync周期,就会将这一帧动画丢弃,并维持上一帧的画面从而导致掉帧。
那么最终目的:平衡CPU和GPU的压力。正确地利用了CPU和GPU资源,使它们均匀地负载,这样子做FPS会保持在60帧。避免出现CPU满载GPU低负载或者GPU满载CPU低负载的情况。

解决办法:

  • GPU满载CPU低负载情况解决办法
    1 尽量使用不透明的视图
    不透明的视图可以极大地提高渲染的速度。其本质就是一个图层混合问题,设置不透明,GPU会忽略掉下面所有的layer,这样可以减少很多不必要的计算。因此可以将table cell及其子视图的opaque属性设为YES。不过一般情况,控件的opaque默认值就是YES,除非我们手动设置。还有控件的backgroundColor属性,我们可以手动设置。对于UIImageView来说,不仅它自身需要时不透明的,它的图片也不能含有alpha通道,否则还会消耗多余的资源。
    2 预渲染图像
    原来在显示图像时,解压和重采样会消耗很多CPU时间;而如果预先在一个bitmap context里画出图像,再缓存这个图像,就能省去这些繁重的工作了。
    3 光栅化(设置layer的shouldRasterize属性为YES)
    对控件设置cornerRadius后对其进行clip或mask操作时,会导致offscreen rendering,而这个是在GPU中进行的,所以快速滑动tableView时,假如圆角对象较多,会导致GPU负载大增。这时候我们可以设置layer的shouldRasterize属性为YES,可以将负载转移给CPU。更为彻底的做法是直接在后台绘制圆角图片然后输出到主线程显示,避免使用圆角、阴影、遮罩等属性。

关于CALayer的shouldRasterize(光栅化)

开启shouldRasterize后,CALayer会被光栅化为bitmap,layer的阴影等效果也会被保存到bitmap中。
当我们开启光栅化后,需要注意三点问题。
如果我们更新已光栅化的layer,会造成大量的offscreen渲染。
因此CALayer的光栅化选项的开启与否需要我们仔细衡量使用场景。只能用在图像内容不变的前提下的:
① 用于避免静态内容的复杂特效的重绘,例如前面讲到的UIBlurEffect
② 用于避免多个View嵌套的复杂View的重绘。
而对于经常变动的内容,这个时候不要开启,否则会造成性能的浪费。
例如我们日程经常打交道的TableViewCell,因为TableViewCell的重绘是很频繁的(因为Cell的复用),如果Cell的内容不断变化,则Cell需要不断重绘,如果此时设置了cell.layer可光栅化。则会造成大量的offscreen渲染,降低图形性能。
当然,合理利用的话,是能够得到不少性能的提高的,因为使用shouldRasterize后layer会缓存为Bitmap位图,对一些添加了shawdow等效果的耗费资源较多的静态内容进行缓存,能够得到性能的提升。

4 特殊的“离屏渲染”方式:CPU渲染
如果我们重写了drawRect方法,并且使用任何Core Graphics的技术进行了绘制操作,就涉及到了CPU渲染。整个渲染过程由CPU在App内同步地完成,渲染得到的bitmap最后再交由GPU用于显示。

  • CPU满载GPU低负载情况解决办法
    5 不要用AutoLayout
那么,我们可以在tableView进行网络请求成功后立刻进行后台的布局计算。将请求到的JSON数组转换为model数组,然后将model数组里的model转换为modelFrame(根据model的各个属性计算出frame)``

你可能感兴趣的:(UITableView性能优化)