03 (OC)* UITableView优化

一:cell注册和初始化

1:不注册cell

 

2:注册类

 

3:注册nib

 

4:storyboard

 

 

二:核心思想

1:UITableView的核心思想是:cell的重用机制。UITbleView只会创建一屏幕(或一屏幕多一点)的cell, 每当cell滑出屏幕时,就会放倒一个集合(或数组)中(这里相当于一个重用池),当要显示某一个位置的cell时,会先根据ReuseIdentifier去集合和数组中去取,如果有直接拿来用,如果没有的话,才会去创建,这样极大地减少了内存的开销。

2:UITableView的两个重要的回调方法是:tableView:cellForRowAtIndexPath:和tableView:heightForRowAtIndexPath:。由于UITableView是继承自UIScrollView的,需要先确定它的contentSize及每个Cell的位置,然后才会把重用的cell放置到对应的位置。UITableView的回调顺序是先多次调用tableView:heightForRowAtIndexPath:来确定cell的位置,然后才会调用tableView:cellForRowAtIndexPath:从而来显示在当前的屏幕的cell。

3:举个例子来说:如果现在要显示100个Cell,当前屏幕显示5个。那么刷新(reload)UITableView时,UITableView会先调用100次tableView:heightForRowAtIndexPath:方法,然后调用5次tableView:cellForRowAtIndexPath:方法;滚动屏幕时,每当Cell滚入屏幕,都会调用一次tableView:heightForRowAtIndexPath:、tableView:cellForRowAtIndexPath:方法。

4::把赋值和计算布局分离。这样让tableView:cellForRowAtIndexPath:只负责赋值,tableView:heightForRowAtIndexPath:只负责计算高度。

 
 

 三:优化方法

1:提前计算并缓存好高度,因为heightForRowAtIndexPath:是调用最频繁的方法

 自动缓存高度

 

一、cell的复用

二、cell的高度

三、cell的渲染

        为了保证TableView的流畅,当快速滑动的时候,cell必须被快速的渲染出来。所以cell渲染的速度必须快。如何提高cell的渲染速度呢?

        (1)当有图像时,预渲染图像,在bitmap context先将其画一遍,导出成UIImage对象,然后再绘制到屏幕,这会大大提高渲染速度。具体内容可以自行查找“利用预渲染加速显示iOS图像”相关资料

        (2)渲染最好时的操作之一就是混合(blending)了,所以我们不要使用透明背景,将cell的opaque值设为Yes,背景色不要使用clearColor,尽量不要使用阴影渐变等;

        (3)由于混合操作是使用GPU来执行,我们可以用CPU来渲染,这样混合操作就不再执行。可以在UIView的drawRect方法中自定义绘制;

        (4)减少subviews的个数和层级。子控件的层级越深,渲染到屏幕上所需要的计算量就越大;如多用drawRect绘制元素,替代用view显示;

        (5)少用subviews的透明图层。对于不透明的View,设置opaque为YES,这样在绘制该View时,就不需要考虑被View覆盖的其他内容(尽量设置Cell的view为opaque,避免GPU对Cell下面的内容也进行绘制);

         (6)避免CALayer特效(shadowPath)。 给Cell中View加阴影会引起性能问题,如下面代码会导致滚动时有明显的卡顿:

        view.layer.shadowColor= color.CGColor;

        view.layer.shadowOffset= offset;

        view.layer.shadowOpacity=1;

        view.layer.shadowRadius= radius;

        (7)我们在cell上添加系统控件的时候,实际上系统都会调用底层的接口进行绘制,大量添加控件时,会消耗很大的资源并且也会影响渲染的性能。当使用默认的UITableViewCell并且在它的ContentView上面添加控件时会相当消耗性能。所以目前最佳的方法还是继承UITableViewCell,并重写drawRect方法。

        (8)在实现drawRect方法的时候,它的参数rect就是我们需要绘制的区域,在rect范围之外的区域我们不需要进行绘制,否则会消耗相当大的资源。

        (9)不要给cell动态添加subView,在初始化cell的时候就将所有需要展示的添加完毕,然后根据需要来设置hide属性显示和隐藏

        (10)异步化UI,不要阻塞主线程.

        (11)滑动时按需加载对应的内容

        参考文章

四、离屏渲染

        下面的情况或操作会引发离屏渲染:

        (1)、为图层设置遮罩(layer.mask);

        (2)、将图层的layer.masksToBounds / view.clipsToBounds属性设置为true;

        (3)、将图层layer.allowsGroupOpacity属性设置为YES和layer.opacity小于1.0;

        (4)、为图层设置阴影(layer.shadow *);

        (5)、为图层设置layer.shouldRasterize=true;

        (6)、具有layer.cornerRadius,layer.edgeAntialiasingMask,layer.allowsEdgeAntialiasing的图层;

        (7)、文本(任何种类,包括UILabel,CATextLayer,Core Text等);

        (8)、使用CGContext在drawRect :方法中绘制大部分情况下会导致离屏渲染,甚至仅仅是一个空的实现。



 
 
参考资料
 
 

posted on 2018-07-11 22:26  风zk  阅读(164)  评论(0编辑  收藏  举报

导航