美文网首页iOS性能优化iOS性能调优
iOS性能优化不归路~~圆角

iOS性能优化不归路~~圆角

作者: LonelyBanana | 来源:发表于2016-07-07 17:45 被阅读2439次

    <h4>一、前言</h6>

    作为一名优秀的程序员应该具有极客思想,尽量把所有代码性能做到最优,但是在企业开发中如果没必要必须这样做还请不要一根筋,所有优化还是要看需求,不要过度优化导致项目延期,FaceBook 首席运营官 雪莉·桑德伯格在《向前一步》里的中心思想就是完成好过完美,成功就是尽可能做最好的选择,然后接受它们。


    <h4>二、为什么会卡顿--摘录自ibireme大神的博客</h6>

    通常来说,计算机系统中 CPU、GPU、显示器是以上面这种方式协同工作的。CPU 计算好显示内容提交到 GPU,GPU 渲染完成后将渲染结果放入帧缓冲区,随后视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示,iOS也是一样的。

    在最简单的情况下,帧缓冲区只有一个,这时帧缓冲区的读取和刷新都都会有比较大的效率问题。为了解决效率问题,显示系统通常会引入两个缓冲区,即双缓冲机制。在这种情况下,GPU 会预先渲染好一帧放入一个缓冲区内,让视频控制器读取,当下一帧渲染好后,GPU 会直接把视频控制器的指针指向第二个缓冲器。如此一来效率会有很大的提升。

    双缓冲虽然能解决效率问题,但会引入一个新的问题。当视频控制器还未读取完成时,即屏幕内容刚显示一半时,GPU 将新的一帧内容提交到帧缓冲区并把两个缓冲区进行交换后,视频控制器就会把新的一帧数据的下半段显示到屏幕上,造成画面撕裂现象

    为了解决这个问题,GPU 通常有一个机制叫做垂直同步(简写也是 V-Sync),当开启垂直同步后,GPU 会等待显示器的 VSync 信号发出后,才进行新的一帧渲染和缓冲区更新。这样能解决画面撕裂现象,也增加了画面流畅度,但需要消费更多的计算资源,也会带来部分延迟。

    iOS使用的就是双缓冲机制,而安卓目前使用的是三缓冲机制。

    <h5>那么卡顿的原因其实就显而易见了</h5>

    img.png

    在 VSync 信号到来后,系统图形服务会通过 CADisplayLink 等机制通知 App,App 主线程开始在 CPU 中计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。随后 CPU 会将计算好的内容提交到 GPU 去,由 GPU 进行变换、合成、渲染。随后 GPU 会把渲染结果提交到帧缓冲区去,等待下一次 VSync 信号到来时显示到屏幕上。由于垂直同步的机制,如果在一个 VSync 时间内,CPU 或者 GPU 没有完成内容提交,则那一帧就会被丢弃,等待下一次机会再显示,而这时显示屏会保留之前的内容不变。这就是界面卡顿的原因。

    从上面的图中可以看到,CPU 和 GPU 不论哪个阻碍了显示流程,都会造成掉帧现象。所以开发时,也需要分别对 CPU 和 GPU 压力进行评估和优化。


    <h4>方法一:CAShapLayer设置蒙版从而实现圆角</h4>
    直接上代码:

    -(UIImageView *)imageView{
        if (!_imageView) {
            _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
            _imageView.image = [UIImage imageNamed:@"heiheihei.jpg"];
            _imageView.contentMode = UIViewContentModeScaleAspectFill;
        }
        return _imageView;
    }
    
    //初始化CAShapeLayer
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];
        //设置shapeLayer路径和圆角弧度
        shapeLayer.path = [UIBezierPath bezierPathWithRoundedRect:
                           self.imageView.bounds cornerRadius:40].CGPath;
        //设置ImageView的蒙版
        self.imageView.layer.mask = shapeLayer;
    
    12CCDC74-AF95-438F-88B1-EF824F5167DA.png

    然后这就完事了,但是这个方法主要占用的是GPU的资源,如果发现GPU本来占用资源就很高了,那么就不要用这个方法了。


    <h4>方法二:直接渲染图片</h4>
    第二种方法就是要直接把图片渲染成圆角,这种方法我认为应该是最优的圆角解决方案啦,如果还有别的方法请交流下。

    -(UIImage *)getImageRadius:(CGFloat)radius andImage:(UIImage *)image{
        
        CGFloat scale = [UIScreen mainScreen].scale;
        UIGraphicsBeginImageContextWithOptions(image.size, NO, scale);
        CGContextRef c = UIGraphicsGetCurrentContext();
        CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
        CGContextAddPath(c, path.CGPath);
        CGContextClip(c);
        [image drawInRect:rect];
        CGContextDrawPath(c, kCGPathFillStroke);
        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return img;
    }
    
    A1549E84-F9DA-4EC1-9B5C-8459AAC6503A.png

    相关文章

      网友评论

      • 7emini:鸡肋啊...... :flushed:
      • 豆小兽:老司机~
        LonelyBanana:@七月天熊 :underage::underage::underage::underage::underage::underage::underage::underage::underage::underage:
      • 话不投机鲜橙多:这个方法呢,ImageView.layer.maskToBounds = YES; ImageView.layer.Cornradios = 40;
        手打的,可能单词拼写错了
        李盛民:@话不投机鲜橙多 放在表格中这样会卡掉的吧…
        6403ff7684ba:@话不投机鲜橙多 好像一直都是用这个,没有特别在意这方面的性能 :joy:
        LonelyBanana:@话不投机鲜橙多 这个方法是最常用的所以就木有写!这种方法的性能有时还会比用CAShapeLayer设置Mask的效率要高!所以还是要看具体情况使用。
      • Joy___:一言不合就上图
        LonelyBanana:@Martin_Joy 哈哈!下次高清无码:heart_eyes::heart_eyes::heart_eyes::heart_eyes:
        Joy___:@LonelyBanana 不喜欢 图太少
        LonelyBanana:@Martin_Joy 喜欢吗:heart_eyes::heart_eyes::heart_eyes:
      • hony啊:抄的吧.
        花前月下:@import 抄不抄的,百度出来的帖子哪个不是一样的。一搜一堆一样的帖子。。。
        LonelyBanana:@import 代码有啥可抄的呢?上面的原理是摘录自http://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/这位大神的博客!~~ :smile: :smile: 这个应该不算抄袭吧?
      • xiao公子:好图
      • xxttw:棒棒

      本文标题:iOS性能优化不归路~~圆角

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