详细讲解UIKit性能调优(续)

上一篇我们说过,在使用 UIKit框架 的过程中,性能优化是永恒的话题 也为大家讲了部分 UIKit性能调优 的知识,这篇文章将继续为大家用实战详细讲解。
颜色格式
像素在内存中的布局和它在磁盘中的存储方式并不相同。考虑一种简单的情况:每个像素有 R G B alpha 四个值,每个值占用 1 字节,因此每个像素占用 4 字节的内存空间。一张 1920*1080 的照片 (iPhone6 Plus 的分辨率 ) 一共有 2,073,600 个像素,因此占用了超过 8Mb 的内存。但是一张同样分辨率的 PNG 格式或 JPEG 格式的图片一般情况下不会有这么大。这是因为 JPEG 将像素数据进行了一种非常复杂且可逆的转化。
当我们打开 JPEG 格式的图片时, CPU 会进行一系列运算,将 JPEG 图片解压成像素数据。显然这个工作会消耗不少时间,所以不应该在滑动时进行,我们应该预先处理好图片。借用 WWDC 上的一页 PPT 来说明:

显示流程
Commit Transaction Decode 在同一帧内进行,如果这两个操作的耗时超过 16.67s Draw Calls 就会延迟到下一帧,从而导致 fps 值的降低。下面是 Commit Transaction 的详细流程:

解码与转换
在第三步的 Prepare 中, CPU 主要处理两件事:
把图片从 PNG JPEG 等格式中解压出来,得到像素数据。
如果 GPU 不支持这种颜色各式, CPU 需要进行格式转换。
比如应用中有一些从网络下载的图片,而 GPU 恰好不支持这个格式,这就需要 CPU 预先进行格式转化。第三个选项 “Color Copied Images” 就用来检测这种实时的格式转化,如果有则会将图片标记为蓝色。
遗憾的是由于我对图片格式不太了解,也不会使用相关工具,并没有能模拟出触发这个选项的场景。我们要记住的是,如果调试时发现有图片被标记为蓝色,说明图片格式出现了一些问题。
图片大小
第四个选项的使用场景不多,我们直接看一下第五个选项 “Color Misaligned Images” 。它表示如果图片需要缩放则标记为**,如果没有像素对齐则标记为紫色。勾选上这个选项并进行调试,可以看到如下场景:
 
图片缩放
demo 中,每个 UIImageView 的大小都是 180x180 ,而只有第二张图片的像素大小是 360x360 。因此除了第二张图片,其他的图片都需要被缩放。图片的缩放需要占用时间,因此我们要尽可能保证无论是本地图片还是从网络或取得图片的大小,都与其 frame 保持一致。
第三个优化是调整所有图片的像素大小以避免不必要的缩放。
离屏渲染
离屏渲染表示渲染发生在屏幕之外,你可能认为这是一句废话。为了真正解释清楚什么是离屏渲染,我们先来看一下正常的渲染通道 (Render-Pass)

正常渲染通道
首先, OpenGL 提交一个命令到 Command Buffer ,随后 GPU 开始渲染,渲染结果放到 Render Buffer 中,这是正常的渲染流程。但是有一些复杂的效果无法直接渲染出结果,它需要分步渲染最后再组合起来,比如添加一个蒙版 (mask)

离屏渲染
在前两个渲染通道中, GPU 分别得到了纹理 (texture ,也就是那个相机图标 ) layer( 蓝色的蒙版 ) 的渲染结果。但这两个渲染结果没有直接放入 Render Buffer 中,也就表示这是离屏渲染。直到第三个渲染通道,才把两者组合起来放入 Render Buffer 中。离屏渲染意味着把渲染结果临时保存,等用到时再取出,因此相对于普通渲染更占用资源。
第六个选项 “Color Offscreen-Rendered Yellow” 会把需要离屏渲染的地方标记为**,大部分情况下我们需要尽可能避免**的出现。离屏渲染可能会自动触发,也可以手动触发。以下情况可能会导致触发离屏渲染:
重写 drawRect 方法
mask 或者是阴影 (layer.masksToBounds, layer.shadow*) ,模糊效果也是一种 mask
layer.shouldRasterize = true
前两者会自动触发离屏渲染,第三种方法是手动开启离屏渲染。
开始调试并勾选 “Color Offscreen-Rendered Yellow” ,会看到这样的场景:
 
离屏渲染
如果没有进行第二步优化,你会发现 label 也是**。可以看到 tabbar statusBar 也是**,这是因为它们使用了模糊效果。图片也是**,这说明它也进行了离屏渲染,观察源码后发现主要原因是它使用了阴影,接下来我们进行第四个优化,在设置阴影效果的四行代码下面添加一行:
1
imgView.layer.shadowPath = UIBezierPath(rect: imgView.bounds).CGPath
这行代码制定了阴影路径,如果没有手动指定, Core Animation 会去自动计算,这就会触发离屏渲染。如果人为指定了阴影路径,就可以免去计算,从而避免产生离屏渲染。
设置 cornerRadius 本身并不会导致离屏渲染,但很多时候它还需要配合 layer.masksToBounds = true 使用。根据之前的总结,设置 masksToBounds 会导致离屏渲染。解决方案是尽可能在滑动时避免设置圆角,如果必须设置圆角,可以使用光栅化技术将圆角缓存起来:
1
2
3
4
5
//  设置圆角
label.layer.masksToBounds = true
label.layer.cornerRadius = 8
label.layer.shouldRasterize = true
label.layer.rasterizationScale = layer.contentsScale
快速路径
还记得之前将离屏渲染和渲染路径时的示意图么,离屏渲染的最后一步是把此前的多个路径组合起来。如果这个组合过程能由 CPU 完成,就会大量减少 GPU 的工作。这种技术在绘制地图中可能用到。
第七个选项 “Color Compositing Fast-Path Blue” 用于标记由硬件绘制的路径,蓝色越多越好。
变化区域
刷新视图时,我们应该把需要重绘的区域尽可能缩小。对于未发生变化的内容则不应该重绘,第八个选项 “Flash updated Regions” 用于标记发生重绘的区域。一个典型的例子是系统的时钟应用,绝大多数时候只有显示秒针的区域需要重绘:
 
重绘区域
原文来自: bestswifter
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值