楼主: z74646
935 0

[其他] UIKit性能调优该怎么做(续) [推广有奖]

  • 0关注
  • 1粉丝

本科生

75%

还不是VIP/贵宾

-

威望
0
论坛币
300 个
通用积分
0
学术水平
0 点
热心指数
1 点
信用等级
0 点
经验
890 点
帖子
55
精华
0
在线时间
12 小时
注册时间
2014-2-26
最后登录
2016-7-2

楼主
z74646 发表于 2016-6-16 23:29:58 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

上一篇我们说过,在使用UIKit框架http://www.maiziedu.com/course/18/的过程中,性能优化是永恒的话题也为大家讲了部分UIKit性能调优的知识,这篇文章将继续为大家用实战详细讲解。



颜色格式

像素在内存中的布局和它在磁盘中的存储方式并不相同。考虑一种简单的情况:每个像素有RGBalpha四个值,每个值占用1字节,因此每个像素占用4字节的内存空间。一张1920*1080的照片(iPhone6 Plus的分辨率)一共有2,073,600个像素,因此占用了超过8Mb的内存。但是一张同样分辨率的PNG格式或JPEG格式的图片一般情况下不会有这么大。这是因为JPEG将像素数据进行了一种非常复杂且可逆的转化。

当我们打开JPEG格式的图片时,CPU会进行一系列运算,将JPEG图片解压成像素数据。显然这个工作会消耗不少时间,所以不应该在滑动时进行,我们应该预先处理好图片。借用WWDC上的一页PPT来说明:


显示流程

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


解码与转换

在第三步的Prepare中,CPU主要处理两件事:


把图片从PNGJPEG等格式中解压出来,得到像素数据。



如果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也是**。可以看到tabbarstatusBar也是**,这是因为它们使用了模糊效果。图片也是**,这说明它也进行了离屏渲染,观察源码后发现主要原因是它使用了阴影,接下来我们进行第四个优化,在设置阴影效果的四行代码下面添加一行:

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


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Kit 怎么做 Transaction animation contents iPhone6 分辨率 图片 文章 照片

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-5 13:01