Fuck iOS EveryDay

001性能优化-02-界面优化.md

2020-06-16  本文已影响0人  修_远

[TOC]

基础优化方向

  1. 使用 ARC 管理内存

  2. 在正确的地方使用 reuseIdentifier

    • tableview 用 tableView:cellForRowAtIndexPath: 为 rows 分配 cells 的时候,他的数据应该重用自 UITableViewCell
  3. 尽量将 views 设置为不透明(Opaque)

  4. 避免过于庞大的 XIB

  5. 不要阻塞主线程

    • 用于不要是主线程承担过多。因为UIKit在主线程上做所有工作,

    • 渲染、管理触摸反应、回应输入等都需要在主线程上完成

    • 大部分阻碍主线程的情形是你的APP在做一些涉及到读写外部资源的 I/O 操作,比如存储或者网络:

      image
  1. 不要在 viewWillAppear 中做费时的操作

    • viewWillAppear,在 view 显示之前被调用,处于效率考虑,方法中不要处理复杂费时操作。
    • 只能在该方法中设置 view 的显示属性之类的简单事情,例如背景色、字体等。否则,会明显感觉到 view 有卡顿或者延迟。

图片处理

  1. 在 ImageView 中调整图片大小。

  2. 保证图片大小和 UIImageView 大小相同。

    如果要在 UIIImageView 中显示一个来自 bundle 的图片,你应保证图片的大小和 UIImageView 大小相同。

  3. 在运行中缩放图片是耗费资源的,特别是 UIImageView 嵌套在 UIScrollView 中的情况下。

  4. 处理网络图片。如果图片是从远端服务器加载的,你无法控制图片大小。那么就在下载完成之后,最好是在 background thread中,缩放一次,然后在 UIImageView 中使用缩放之后的图片。

UITableView 优化

view相关操作

缓存相关操作

数据加载相关操作

CPU 和 GPU 层优化

本质上是降低 CPU、GPU的工作,从这两个方面入手去提升性能

CPU 层面的优化

GPU 层面的优化

离屏渲染优化

如何高性能的画一个圆角?

视图和圆角的大小对帧率并没有什么影响,数量最核心的影响因素

image

这个是我们最常规的设置方式,但不可取,因为会触发离屏渲染

image

什么是 “离屏渲染”?

离屏渲染就是在当前屏幕缓冲区外,新开辟一个缓冲区进行操作。

为何要避免离屏渲染?

CPU、GPU 在绘制渲染视图是做了大量的工作。离屏渲染发生在 GPU 层面上,会创建新的渲染缓缓冲区,会触发 OpenGL 的多通道渲染管线,图像上下文切换会早晨额外的开销,增加 GPU 工作量。如果CPU、GPU累计耗时 16.67 ms还没有完成,就会造成卡顿掉帧。

圆角属性、蒙层遮罩 都会触发离屏渲染。指定以上属性,标记了它在新的图形上下文中,在未愈合之前,不可以用于显示的时候就触发了离屏渲染。

离屏渲染消耗性能的原因?

哪些操作会触发离屏渲染?

  1. layer.shouldRasterzize:光栅化

    • 光栅化概念:将图转化为一个个栅格组成的图像
    • 光栅化特点:每个元素对应帧缓冲区的一像素
    • 光栅化限制:系统给光栅化限制了内存,如果超过就会触发离屏渲染,所以cell中一般不使用
  2. mask:遮罩

  3. shadows:layer.shadowXXX,如果设置了 layer.shadowPath 就不会产生离屏渲染

  4. group opacity:不透明,layer属性

  5. edge antialiasing:抗锯齿

  6. cornerRadius:圆角。同时设置 layer.masksToBounds = YES; layer.cornerRadius 大于0,考虑通过 CoreGraphics 绘制圆角,或者让美工提供圆角图片

  7. 渐变

  8. drawRect

离屏渲染 VS CPU 渲染

上面说到了,所有不在 GPU 的当前屏幕缓冲区进行的渲染都叫离屏渲染,还有另外一种特殊的离屏渲染,叫“CPU 渲染”。

由于 GPU 的浮点运算能力比 CPU 强,CPU 渲染的效率可能不如离屏渲染。但如果只是实现一个简单的效果,直接使用CPU渲染就可以,因为离屏渲染涉及到缓冲区创建以及上下文切换等耗时操作。

如何检测离屏渲染?

  1. 模拟器:Debug->Color Off-screen Rendered

    image image image

    可以看到图片亮黄色部分就是离屏渲染的视图

  2. 真机:xcode9之后可以不用 Instrument 了,运行程序之后:Debug -> View Debugging -> Rendering -> Color Offscreen-Rendered Yellow

    设置路径 image

离屏渲染的解决思路

  1. 预排班,提前计算

    在接收到服务器端返回的数据后,尽量将 CoreText 排版的结果、单个空间的高度、cell 整体的高度提前计算好,将其存储在模型的属性中。需要使用时,知己耳聪模型中往外取,避免了计算的过程。

    尽量少用 UILabel,可以使用 CALayer。避免使用 AutoLayout 的自动布局,才去纯代码的方式

  2. 预渲染,提前绘制

    圆形的图标可以提前在:接收到网络返回数据时,后台线程进行处理,直接存储在模型数据中,回到主线程后直接调用

    避免使用 CALayer 的 Border、Corner、Shadow、Mask 等技术,这些都会触发离屏渲染

  3. 异步绘制

  4. 全局并发线程

  5. 高效的图片异步加载

图层混合优化

  1. 怎么检测图层混合

    在下面 instrument 工具介绍中有给出

  2. 怎么避免图层混合

    • 确保控件的 Opaque 属性设置为 true
    • 确保控件的 背景色 和父视图的背景色一致 且不透明
    • 如无特殊需要,不要设置低于 1 的 alpha 值
    • 确保 UIImage 没有alpha 通道
    • UILabel iOS8以后设置背景色为非透明 和 设置 label.layer.masksToBounds=YES,就可以让label只渲染给定的size区域,解决 UILabel 的图层混合问题

instrument 工具

上面讲到了如何检测离屏渲染,除了离屏渲染 Rendering 还有其他几种调试类型

opaque 绘制优化

这个值不是决定视图是否是透明的,而是给绘制系统提供一个个性能优化的开关

red + green = yellow

image

在第一篇文章中介绍了一个公式:

R = S + D * (1 - Sa)

- R:像素RGB
- S:源色彩(顶端纹理)
- D:目标颜色(低一层的纹理)
- Sa:源色彩的透明度

R = 1 + 0 * (1-0.5)
G = 0 + 1 * (1-0.5)
B = 0 + 0 * (1-0.5)
A = 1 + 0.5 * (1-0.5)

而当 Sa=1 时,R=S,也就是说。这个时候不管目标颜色是什么,GPU 都不需要做任何计算合成。只需要简单的从这个层进行拷贝,节省了GPU大量的工作量。

上一篇 下一篇

猜你喜欢

热点阅读