iOS的阴影绘制及性能优化
今天来讲讲iOS开发过程中的阴影绘制及其潜在的绘图性能问题。虽然在开发过程中,我们使用阴影功能的机会不是很多,但是如果用了,有可能引起如卡顿等性能问题,所以,还是有必要来探究一下阴影的绘制过程,及如何提高阴影的绘制性能。
阴影绘制
阴影可以通过设置layer层的shadowXXX属性,就可以很方便的为UIView添加阴影效果,但是不同的设置方式可能产生性能方面的问题,下面介绍一下不同方式对性能的影响。
方式一
通过设置下面的4个属性,就可以添加阴影,这种方式可能产生性能问题,因为绘制阴影而不指定阴影路径,在绘制阴影过程中,就会产生大量的离屏渲染(Offscreen-Rendered),非常消耗性能,进而造成动画卡顿的问题。
离屏渲染
造成离屏渲染的原因很多,比如:遮罩、阴影、抗锯齿等等,而阴影造成离屏渲染的原因是:iOS会先绘制目标的阴影,然后绘制目标的本身,在没有指定阴影的绘制路径时,iOS视图在每次绘制前都会递归的精确计算每个子层阴影的路径,这会非常消耗性能,也是导致卡顿的根源。
所以,如果绘制的阴影不是很多的情况下,该方法不会消耗大量性能,绘制就会比较简单,代码量也少。
// 设置阴影颜色
self.imageView1.layer.shadowColor = [UIColor orangeColor].CGColor;
// 设置阴影的偏移量,默认是(0, -3)
self.imageView1.layer.shadowOffset = CGSizeMake(4, 4);
// 设置阴影不透明度,默认是0
self.imageView1.layer.shadowOpacity = 0.8;
// 设置阴影的半径,默认是3
self.imageView1.layer.shadowRadius = 4;

方式二
为了减少因为没有设置shadowPath造成绘制阴影时大量重复绘制的问题,我们可以指定阴影的绘制路径,这样在绘制阴影时,就可以在多个layer层共享同一个路径的阴影,以此来提高性能,下面是苹果官方文档是解释:
/* When non-null this path defines the outline used to construct the
* layer's shadow instead of using the layer's composited alpha
* channel. The path is rendered using the non-zero winding rule.
* Specifying the path explicitly using this property will usually
* improve rendering performance, as will sharing the same path
* reference across multiple layers. Upon assignment the path is copied.
* Defaults to null. Animatable. */
@property(nullable) CGPathRef shadowPath;
shadowPath的注释大意就是说如果不指定路径,就会使用layer层的alpha通道的混合,而如果指定阴影路径,就会在多个layer层之间共享同一路径,以此来提高性能。
有关什么是layer层的混合,可以这样理解:iOS在渲染每一帧时,都会计算每一个像素的颜色,如果上层layer不透明,就只取上层layer的颜色;而如果上层layer存在透明度时(alpha通道),则需要混合每一层的颜色来计算最终的颜色。如果layer越多,计算量就越大,也就比较耗性能。所以,在开发中,要尽量减少视图的透明层。
具体代码示例,具体是功能就是绘制一个边框阴影:
_imageView.layer.shadowColor = [UIColor yellowColor].CGColor;//shadowColor阴影颜色
_imageView.layer.shadowOffset = CGSizeMake(0,0);//shadowOffset阴影偏移,默认(0, -3),这个跟shadowRadius配合使用
_imageView.layer.shadowOpacity = 1;//阴影透明度,默认0
_imageView.layer.shadowRadius = 3;//阴影半径,默认3
//路径阴影
UIBezierPath *path = [UIBezierPath bezierPath];
float width = _imageView.bounds.size.width;
float height = _imageView.bounds.size.height;
float x = _imageView.bounds.origin.x;
float y = _imageView.bounds.origin.y;
float addWH = 10;
CGPoint topLeft = _imageView.bounds.origin;
CGPoint topMiddle = CGPointMake(x+(width/2),y-addWH);
CGPoint topRight = CGPointMake(x+width,y);
CGPoint rightMiddle = CGPointMake(x+width+addWH,y+(height/2));
CGPoint bottomRight = CGPointMake(x+width,y+height);
CGPoint bottomMiddle = CGPointMake(x+(width/2),y+height+addWH);
CGPoint bottomLeft = CGPointMake(x,y+height);
CGPoint leftMiddle = CGPointMake(x-addWH,y+(height/2));
[path moveToPoint:topLeft];
//添加四个二元曲线
[path addQuadCurveToPoint:topRight
controlPoint:topMiddle];
[path addQuadCurveToPoint:bottomRight
controlPoint:rightMiddle];
[path addQuadCurveToPoint:bottomLeft
controlPoint:bottomMiddle];
[path addQuadCurveToPoint:topLeft
controlPoint:leftMiddle];
//设置阴影路径
_imageView.layer.shadowPath = path.CGPath;

综上,以后开发过程中,如果用到阴影效果,在视图图层不是很多,阴影视图计算量少的情况下,可以直接设置阴影,但是如果图层较多,阴影的计算量较大,则要考虑使用path的方式。(本文主要参考互联网,版本归原作者所有)
参考资料
iOS的阴影绘制及性能优化的更多相关文章
- iOS性能优化-异步绘制
参考地址:https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/ 很久以前就看过这篇文章,但是也只是看过就过了,没有去整 ...
- iOS程序性能优化
iOS程序性能优化 一.初级 使用ARC进行内存管理 在iOS5发布的ARC,它解决了最常见的内存泄露问题.但是值得注意的是,ARC并不能避免所有的内存泄露.使用ARC之后,工程中可能还会有内存泄露, ...
- iOS 程序性能优化
前言 转载自:http://www.samirchen.com/ios-performance-optimization/ 程序性能优化不应该是一件放在功能完成之后的事,对性能的概念应该从我们一开始写 ...
- [iOS Animation]-CALayer 性能优化
性能优化 代码应该运行的尽量快,而不是更快 - 理查德 在第一和第二部分,我们了解了Core Animation提供的关于绘制和动画的一些特性.Core Animation功能和性能都非常强大,但如果 ...
- iOS进阶之页面性能优化
转载:http://www.jianshu.com/p/1b5cbf155b31 前言 在软件开发领域里经常能听到这样一句话,"过早的优化是万恶之源",不要过早优化或者过度优化.我 ...
- iOS 性能优化总结
卡顿产生的原因 在 VSync信号到来后,系统图形服务会通过 CADisplayLink等机制通知 App,App主线程开始在 CPU中计算显示内容,比如视图的创建.布局计算.图片解码.文本绘制等.随 ...
- iOS页面性能优化
前言 在软件开发领域里经常能听到这样一句话,“过早的优化是万恶之源”,不要过早优化或者过度优化.我认为在编码过程中时刻注意性能影响是有必要的,但凡事都有个度,不能为了性能耽误了开发进度.在时间紧急的情 ...
- iOS开发系列之性能优化(上)
本篇主要记录一下我对界面优化上的一些探索.关于时间优化的探索将会在中篇里进行介绍.下篇将主要介绍一些耗电优化.安装包瘦身的探索. ### 1.卡顿原理 要了解卡顿原理,需要对帧缓冲区.垂直同步.CPU ...
- iOS性能优化-数组、字典便利时间复杂
上图是几种时间复杂度的关系,性能优化一定程度上是为了降低程序执行效率减低时间复杂度. 如下是几种时间复杂度的实例: O(1) return array[index] == value; 复制代码 O( ...
随机推荐
- 数据库--释放mysql数据库资源
背景 nikeodong之前做了项目的数据库主从,在全备的过程发现数据库是越来越大了:最后发现是资源不释放的问题. 目的 为了解决mysql资源不释放的问题. 步骤 1.vim /etc/my.cnf ...
- Unity 游戏框架搭建 (六) 关于框架的一些好文和一些思考
在进行项目架构阶段,游戏框架可以解决一部分问题.剩下的架构问题还需要根据不同的项目解决.总之游戏框架是游戏架构的一部分. 关于锤子和钉子: 最近又拿起了<代码大全>和<暗时间 ...
- 恐怖的ifdown eth0;0
下午闲的蛋疼,随手给测试机配了个浮动地址eth0:0. ping了下OK,内网访问没问题. 准备收手的时候,瞄了一眼ifcfg-eth0:0的配置,发现广播地址BROADCAST写成了BOADCAST ...
- Java 标准DBUtil 写法
package xueruan.com.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql ...
- 面向对象15.3String类-常见功能-判断
/*3.判断 * 3.1两个字符串内容是否相同? * boolean equals(Object obj)(参数是Object,不是String,因为equals是覆盖Object里面的equals方 ...
- Oozie时出现Exception in thread "main" java.lang.UnsupportedClassVersionError: com/mysql/jdbc/Driver : Unsupported major.minor version 52.0?
不多说,直接上干货! 问题详情 [hadoop@bigdatamaster oozie--cdh5.5.4]$ bin/ooziedb.sh create -sqlfile oozie.sql -ru ...
- js模块加载之AMD和CMD
当我写这篇文章的时候,sea.js已经逐渐退出历史的舞台,详细链接.不过任何新事物的出现都是对旧事物的取其精华,去其糟粕,所以了解一下以前模块的加载也是一件好事. js模块化的原因自不比多说,看看HU ...
- Java - 初始化
用构造器保证初始化 构造器名称必须与类名完全相同,所以“每个方法首字母必须小写”的风格不适合构造器. 不接受任何参数的构造器叫做默认构造器.Java文档中通常叫做无参构造器. 构造器没有返回值,但与返 ...
- nyoj_471:好多的树(容斥原理)
题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=471 还是直接上代码.. #include<bits/stdc++.h> u ...
- (转)log4j(四)——如何控制不同风格的日志信息的输出?
一:测试环境与log4j(一)——为什么要使用log4j?一样,这里不再重述 1 老规矩,先来个栗子,然后再聊聊感受 import org.apache.log4j.*; //by godtrue p ...