美文网首页收藏ios
UITableView的性能优化

UITableView的性能优化

作者: 白水灬煮一切 | 来源:发表于2019-07-14 23:51 被阅读78次

    cell一定走复用方法;

    cell高度优化计算;->通过数据提前计算好每一个cell高度,再进行cell刷新展示

    cell渲染;—> 减少cell上子视图的个数以及子视图层级

                               避免动态添加子视图(提前添加好,根据数据进行隐藏和显示)

                                避免使用CALayer特效,比如 阴影、渐变颜色、裁边,改用图片代替阴影和圆            

                               尽量不要在cell上进行复杂的数据处理,按需加载对应的cell

    cell离屏渲染;—>不要添加遮罩layer.mask

                                        不要使用裁边layer.masksToBounds

                                         不要使用阴影(使用设置阴影偏移量)

                                          drawRect方法不要进行重写

                                    (圆角、阴影 可以使用图片或者CALayer自己绘制)

    一、cell的复用

    二、cell的高度

    说到cell高度优化问题,可能大家都知道去计算并缓存cell的高度。今天说另一种方法。我们分为两种cell,一种是定高的cell,另外一种是动态高度的cell。

    (1)定高的cell,应该采用如下方式:

            self.tableView.rowHeight = 100;

    (2)动态高度的cell

            我们需要实现它的代理,来给出高度:避免在代理计算cell高度,在数据出来后就根据数据去计算出cell对应的高度,在代理里面直接进行高度的返回!

    三、cell的渲染

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

    图片提前加载到内存中;cell背景颜色不要使用阴影、渐变;适量使用CALayer绘制视图;减少cell上子视图的个数、层数、复杂度;避免CALayer特效;避免动态往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)滑动时按需加载对应的内容

    四、离屏渲染

    裁边、阴影、drawRect;

    通过CALayer进行绘制圆角、阴影;或者切图圆角。

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

            (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 :方法中绘制大部分情况下会导致离屏渲染,甚至仅仅是一个空的实现。

    1、优化方案

            官方对离屏渲染产生性能问题也进行了优化:

            iOS 9.0 之前UIimageView跟UIButton设置圆角都会触发离屏渲染。iOS 9.0 之后UIButton设置圆角会触发离屏渲染,而UIImageView里png图片设置圆角不会触发离屏渲染了,如果设置其他阴影效果之类的还是会触发离屏渲染的。

    优化方案1:使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角

            UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];

            imageView.image = [UIImage imageNamed:@"myImg"];

            //开始对imageView进行画图

            UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);

            //使用贝塞尔曲线画出一个圆形图

            [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.frame.size.width] addClip];

            [imageView drawRect:imageView.bounds];

            imageView.image = UIGraphicsGetImageFromCurrentImageContext();

            //结束画图

            UIGraphicsEndImageContext();

            [self.view addSubview:imageView];

    优化方案2:使用CAShapeLayer和UIBezierPath设置圆角

            UIImageView *imageView=[[UIImageViewalloc]initWithFrame:CGRectMake(100,100,100,100)];

            imageView.image=[UIImageimageNamed:@"myImg"];

            UIBezierPath *maskPath=[UIBezierPathbezierPathWithRoundedRect:imageView.boundsbyRoundingCorners:UIRectCornerAllCornerscornerRadii:imageView.bounds.size];

            CAShapeLayer *maskLayer=[[CAShapeLayeralloc]init];

            //设置大小

            maskLayer.frame=imageView.bounds;

            //设置图形样子

            maskLayer.path=maskPath.CGPath;

            imageView.layer.mask=maskLayer;

            [self.viewaddSubview:imageView];

            对于方案2需要解释的是:

            CAShapeLayer继承于CALayer,可以使用CALayer的所有属性值;CAShapeLayer需要贝塞尔曲线配合使用才有意义(也就是说才有效果);使用CAShapeLayer(属于CoreAnimation)与贝塞尔曲线可以实现不在view的drawRect(继承于CoreGraphics走的是CPU,消耗的性能较大)方法中画出一些想要的图形,CAShapeLayer动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言,其效率极高,能大大优化内存使用情况。总的来说就是用CAShapeLayer的内存消耗少,渲染速度快,建议使用优化方案2。

    (2)shadow优化

            对于shadow,如果图层是个简单的几何图形或者圆角图形,我们可以通过设置shadowPath来优化性能,能大幅提高性能。示例如下:

            imageView.layer.shadowColor=[UIColorgrayColor].CGColor;

            imageView.layer.shadowOpacity=1.0;

            imageView.layer.shadowRadius=2.0;

            UIBezierPath *path=[UIBezierPathbezierPathWithRect:imageView.frame];

            imageView.layer.shadowPath=path.CGPath;

            我们还可以通过设置shouldRasterize属性值为YES来强制开启离屏渲染。其实就是光栅化(Rasterization)。既然离屏渲染这么不好,为什么我们还要强制开启呢?当一个图像混合了多个图层,每次移动时,每一帧都要重新合成这些图层,十分消耗性能。当我们开启光栅化后,会在首次产生一个位图缓存,当再次使用时候就会复用这个缓存。但是如果图层发生改变的时候就会重新产生位图缓存。所以这个功能一般不能用于UITableViewCell中,cell的复用反而降低了性能。最好用于图层较多的静态内容的图形。而且产生的位图缓存的大小是有限制的,一般是2.5个屏幕尺寸。在100ms之内不使用这个缓存,缓存也会被删除。所以我们要根据使用场景而定。

    (3)其他的一些优化建议

            1.当我们需要圆角效果时,可以使用一张中间透明图片蒙上去

            2.使用ShadowPath指定layer阴影效果路径

            3.使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)

            4.设置layer的opaque值为YES,减少复杂图层合成

            5.尽量使用不包含透明(alpha)通道的图片资源

            6. 尽量设置layer的大小值为整形值

            7.直接让美工把图片切成圆角进行显示,这是效率最高的一种方案

            8.很多情况下用户上传图片进行显示,可以让服务端处理圆角

            9.使用代码手动生成圆角Image设置到要显示的View上,利用UIBezierPath(CoreGraphics框架)画出来圆角图片

    相关文章

      网友评论

        本文标题:UITableView的性能优化

        本文链接:https://www.haomeiwen.com/subject/vsuwkctx.html