UITableView的性能优化

UITableView是最常用的控件,所以一个滑动流畅的tableview对于用户体验是多么重要。下面整理了一些针对UITableView的性能优化的方法。

重用UITableViewCell

这一点很多人都知道,就是要利用苹果提供的cell重用机制,不要每次都重新创建cell。在tableView:cellForRowAtIndexPath:要尽快返回cell。

很多人习惯在tableView:cellForRowAtIndexPath:方法中对cell进行数据绑定,但这有待改进。因为tableView:cellForRowAtIndexPath:执行时cell还没有展示出来。下面是苹果原文:

Don’t bind data at cellForRowAtIndexPath: method ‘cause at this time cell is not displayed yet. Instead use tableView:willDisplayCell:forRowAtIndexPath: method in the delegate of UITableView.

正确的做法是在tableView:willDisplayCell:forRowAtIndexPath:中进行数据绑定。

Cell的高度计算

对于cell高度静态的UITableView来说,这一点无关紧要。但是动态高度的cell一般有两种实现方式:

  1. 通过autolayout来自动计算高度
  2. 手动实现tableView:heightForRowAtIndexPath:方法来动态计算高度

其中,通过autolayout需要计算cell的约束,这么做的效率会比较低,在约束较多时可能引起tableview滚动的卡顿。所以最好的方式是手动计算cell的高度,tableView:heightForRowAtIndexPath:这个方法要尽快返回。必要时,还可以缓存cell的高度,或者进行高度预计算。

避免混合操作

在图像渲染中最慢的操作之一就是混合(blending)。所以,要尽可能避免cell中各种透明控件,将它们的opaque属性都置为YES

layer的圆角设置其实也是执行了混合操作,所以可以将layer的shouldRasterize设为YES,这样layer会被渲染成一个bitmap,并缓存起来,等下次使用时就不用重新渲染了。

对layer的缓存处理实际上叫做光栅化,光栅化对于阴影的渲染同样能够优化。对于经常改动的,不要采用光栅化,会造成性能消耗,而对于相对静态的、复杂的界面,最好采用光栅化。

图片的加载与缓存

cell中的图片一定要采用异步加载的方式,否则势必造成滑动卡顿。使用UIImageView+AFNetworking.h中的方法就能很方便的进行异步加载,当加载失败时,会显示缺省图片。同时,AFNetworking实现了对图片的内存缓存和请求缓存,如果请求或图片已缓存,就不会重新请求图片,提升了图片加载的速度。

扁平化

由于渲染复杂的View非常耗时,所以一种思路是,通过Core Graphics进行重绘,将所有subViews绘制成一张图片,通过消除view的层级来提高效率,这对于一些复杂的界面效果很明显。但缺点就是重绘比较复杂,对于一些简单界面没有必要这么做。

异步渲染

因为更新界面的操作一定要放在主线程当中,所以可以将一些渲染工作放到其他线程来做,最后再回到主线程更新界面。Facebook开源的框架AsyncDisplayKit应用类似这样的思路。

参考