这周公众号发布的以下文章:
本期知识小集的主要内容包括:
- 一些 UI 性能优化的 tips
- 你的项目中还用热修复吗?
- Assets的几个方便用法
- 两种 App 启动连续闪退检测策略
一些 UI 性能优化的 tips
作者 : halohily
-
圆角效果:圆角效果的优化老生常谈,产生性能问题的根源在于原生圆角效果带来的离屏渲染开销。通常我们推荐直接使用圆角的素材,或者提前在子线程将图片进行圆角裁剪,这两者原理相同。除此之外,还有一种思路是在需要圆角的视图最上层添加一个中空的圆角遮罩层,以此来做出圆角效果。这个遮罩层和被盖在下面的视图在显示时会由 GPU 进行图层混合,而图层混合的开销远小于离屏渲染。值得一提的是,由于圆角效果通常在一屏中频繁出现,所以这个遮罩的图片素材可以只加载一次,并且应用于每一个圆角视图,避免重复加载。
-
阴影效果:值得注意的是系统原生的阴影实现要求 layer 的
masksToBounds
值为 YES,所以原生的阴影效果和圆角是不兼容的。高效的阴影实现是为阴影指定 shadowPath,如果你还没用的话,不妨试一下。 -
适时替换轻量控件:
@ibireme
在他的性能优化文章中提出在合适的时候用 CALayer 替换 UIView,这确实有效,不过盲目替换往往会造成代码维护的困难。这里举两个适合的场景:绘制线条时,完全可以替换。以及静态展示图片时,将图片对象赋值给 layer 的 content 属性,也完全可以达到效果。 -
图片解码:图片解码的知识不再赘述,值得一提的是,对于不同的图片格式,不同的解码算法,或者使用系统解码方法时的不同参数设置,都会影响解码性能,如果有这方面瓶颈的,不妨做多种尝试。
再说一个经典的例子:为了实现一个简单的画板需求,有人会在 UIView 上频繁调用
drawRect
方法进行新笔划的绘制,殊不知有一个天生的专用图层对象
CAShapeLayer
是很适合做这件事的。CAShapeLayer 不需要像普通 CALayer 一样创建寄宿图,不会造成巨量内存的使用,并且它使用了硬件加速。
UI 性能优化时,我们常常需要实时监测帧率。这里讲一下
@ibireme
的帧率监测工具
YYFPSLabel
的实现原理:使用 CADisplayLink,在每帧的回调事件中,计数器 c 加一,并且累计时间间隔 t 也进行更新。当时间间隔够 1 秒后,使用 c/t 计算出过去 1 秒的帧率,而后计数器清零,时间戳更新为当前时间戳,再重复之前步骤。因此 YYFPSLabel 的帧率更新周期在 1 秒左右。
你的项目中还用热修复吗?
作者 : Lefe_x
前两天知识小集群里有人讨论关于热修复的问题,对此我非常感兴趣,今天作为一个小集和大家探讨一下。虽然目前苹果严禁带有热修复功能的 APP 上线,一旦发现,将增加审核时间(大约是一周的时间)。苹果主要考虑到了安全问题,避免给自己找事,所以干脆禁用了 JSPatch。但是 JSPatch 使用的 API 并没有违反苹果的规定,他也就没有一个十足的理由拒绝你的 APP 上线。这样就导致还有很多公司在悄悄地用 JSPatch。不过原理基本都是对 JSPatch 进行混淆后使用,当然如果你有能力自己实现一个 JSPatch 也可以。
被拒苹果的拒绝理由大概是这样的:
目前我了解到市面上主要通过以下几种方式进行混淆(如果对这个话题感兴趣,后续我们会在【知识小集】公众号 进一步探讨):
方式一:使用官方提供的混淆方式
目前使用官方提供的 JSPatch 服务任然可以过审,据说也是通过静态混淆-宏定义 这中方式。
方式二:Bugly(静态混淆-宏定义)
Bugly 提供了热修复功能,它提供了一种对 JSPatch 混淆的方式。在
BuglyHotfixConfuse_pch.h
文件中把需要混淆的类名方法名替换掉。有兴趣的读者可以在
这里
查看详细代码。
方式三:自己混淆
自己混淆当然是最保守的,苹果很难察觉。某天网上爆出一个
ZipArchive
安全漏洞,而这个漏洞的一个条件就是使用了类似 JSPatch 这种可以动态执行脚本的功能,而被爆出的 APP 经查确实使用混淆后 JSPatch,而他们采用的混淆方式也就是自己混淆。所以自己混淆 JSPatch 这条路是通的。自己混淆主要是理解 JSPatch 的原理,换一种方式来实现。
Assets的几个方便用法
作者 : 高老师很忙
Assets 想必大家都使用过,今天聊几个 Assets 比较方便的用法。
-
在工程中,某个通用的颜色,我们可能会用宏或者全局变量来表示,这样可以方便大家的使用,但有一个弊端,在
storyboard
或者xib
布局的时候,设置颜色依旧要去设置具体的RGB值;而Assets给我们提供了一个很方便的功能,可以创建New Color Set
,就弥补了刚才方案的缺陷(如下图),并且代码中使用也很方便。
-
在需要拉伸图片的时候,通常会使用 UIImage 的 API 的
-[UIImage resizableImageWithCapInsets:resizingMode:]
这个方法;而 Assets 为我们提供了 Slicing 的功能(如下图),在 Assets 中直接设置后,在 storyboard 和 xib 中就可以直接显示拉伸后的图片,在代码中使用也及其方便,直接用-[UIImage imageNamed:]
方法即可。
-
如果是 Universal 的工程,同一个 UIImageView,在 iPhone 中显示图片 A,在 iPad 中显示图片 B,Assets 可以很方便的通过
Devices
设置,会让代码看着很清爽,不会存在判断机型再去设置图片的恶心代码。在设置横竖屏的时候也可以充分利用Width Class
和Height Class
两个参数(如下图)。
我觉得这 3 个用法在工作中还是很实用的,当然 Assets 还有其他很好用的功能,欢迎大家一起交流。