本篇主要记录一下我对界面优化上的一些探索。关于时间优化的探索将会在中篇里进行介绍。下篇将主要介绍一些耗电优化、安装包瘦身的探索。

### 1、卡顿原理

要了解卡顿原理,需要对帧缓冲区、垂直同步、CPU 和 GPU 几个词进行一下了解,然后综合起来,就可以得到卡顿的答案。本篇我就按照自己的理解来进行描述,如有不当,欢迎指正。

#### 1.1、帧缓冲区

听起来很高大上,其实就是用来存放每一帧画面数据的一个“仓库”,一个仓库只存放一帧画面的数据,iOS 一直是双缓存,就是有两个仓库,存当前帧数据的叫“正式仓库”,存下一帧数据的叫“预备仓库”。

当正式仓库的数据被取走后,两者身份交换,原来的预备仓库转正为正式仓库,原来的正式仓库变成预备仓库。

#### 1.2、垂直同步 (VSync)

就是一个“信号”,通知 app 该开始准备往预备仓库里存放数据了,系统过一会就要来取,这个时间大概是16毫秒。

#### 1.3、CPU (中央处理器)

主要的工作有:正式对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制。我们可以理解为负责包裹内部的处理工作,简称“打包”。

#### 1.4、GPU (图形处理器)

主要的工作有:将 CPU 计算好的内容进行变换、合成、渲染等处理,然后将渲染结果提交到帧缓冲区。我们可以理解为,对 CPU 给过来的包裹进行分类、排列等操作后,存放到仓库里去,简称“入库”。

#### 1.5、卡顿原理

当收到系统发过来的 VSync “信号”后,CPU 就开始对这一帧画面的数据进行“打包”,然后交给 GPU 进行“入库”操作,存入到“预备仓库”中。

16毫秒后,预备仓库转正,系统开始读取仓库里的数据,如果这个时候,仓库中的数据还没有准备好,那么系统就会大发雷霆,放弃读取仓库中的数据。

那么这个时候,因为系统的宁缺毋滥,导致了显示器上显示的还是上一帧画面,就造成了卡顿的效果。

### 2、性能优化

作为软件开发工程师的我们,既不能延长16毫秒的处理时间,也不能改变系统的脾气,那我们能做的就是尽量在这个时间内完成数据的准备。要么“打包”快一点,要么“入库”快一点,也就是针对 CPU 和 GPU 的工作进行优化,这就是性能优化的工作了。

#### 2.1、CPU 工作之正式对象的创建和销毁

- UITableViewCell 和 UICollectionViewCell 的复用,可以减少 cell 的创建操作;

- 尽量使用轻量级的对象,可以减少对象的创建时间,比如在不需要事件处理的场景里,使用CALayer 比 UIView 会更加合适;

- 表情键盘使用 UICollectionViewCell 代替 UIButton,可以减少对象的创建操作;

- 对象不涉及UI操作,放到后台线程创建;

- 性能敏感的界面,storyborad的资源消耗>代码创建;

- 推迟对象创建的时间,对象放到多个任务中,比如懒加载;

#### 2.2、CPU 工作之对象属性的调整

- UIView 有一个 CALyer 的属性,UIView 负责事件的处理,CALyer 负责图层的绘制和显示。需要注意的是,CALyer本身是没有属性的,所以当改变 UIView 的显示相关的属性如 frame、bounds 和 transform 的时候,会消耗较多的资源,所以减少对这些属性的一些不必要修改,能减小 CPU 的压力;

#### 2.3、CPU 工作之布局计算

- UITableViewCell 高度提前计算并存储,要用的时候直接读取;

- frame 计算好,较少不必要的修改;

- Autolayout会比直接设置frame消耗更多的CPU资源;

#### 2.4、CPU 工作之文本的计算和排版

- 普通文本可以在子线程用 [NSAttributedString boundingRectWithSize:options:context:] 来计算文本宽高,用 -[NSAttributedString drawWithRect:options:context:] 来绘制文本;

- CoreText 对象占用内存较少,当显示大量文本时,可以用 CoreText 对文本异步绘制;

#### 2.5、CPU 工作之图片的格式转换和解码

- 在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片;

#### 2.6、CPU 工作之图像的绘制

- UITableViewCell 滑动减速的时候才加载图片,可以参考这个[demo](https://github.com/johnil/VVeboTableViewDemo);

- 加载图片时,imageNamed 方法默认加载图片成功后会内存中缓存图片,下次读取会很快;imageWithContentsOfFile 方法不会缓存图片,大图片可以使用该方法;

#### 2.7、GPU 工作之渲染

- 尽量不要让图片和视图的大小超过 GPU 纹理尺寸上限:4096×4096,不然图片还需要经过 CPU 的处理;

- 尽量减少视图数量和层次,并设置视图为不透明,UIView 的不透明属性 (opaque) 默认为 YES,一般设置背景颜色即可;CALayer 的不透明属性 (opaque) 默认为 NO,需要设置为 YES;

- CALayer 的 border、圆角、阴影、遮罩,通常会触发离屏渲染,尽量少用,圆角属性可以使用 CoreGraphics 绘制或使用圆角图片代替,关于离屏渲染的知识,具体可以参考这篇文章:[iOS 图形性能优化](http://www.cocoachina.com/cms/wap.php?action=article&id=25543);

- 图片的 size 最好刚好跟 UIImageView 的 size 保持一致,这涉及到像素对齐的知识,也可以在上面这篇文章中详细了解;

最后郑重声明,本篇里只是记录一下我的个人理解和代码实践,资料大量参考了这篇文章:[iOS 保持界面流畅的技巧](https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/),作者是写出了 YYKit 框架的大佬,想要深入学习的朋友请移步。

本篇的界面优化就记录到这里,后面会持续更新,欢迎指正。

iOS开发系列之性能优化(上)的更多相关文章

  1. Android开发系列之性能优化

    一直想整理一篇关于Android性能优化的博客,正好今天借鉴一些书籍资料,总结一下自己对于这块的一些认识.相信大家都听说过16ms的原则,即每两个画面之间的绘制时间间隔不能超过16ms,否则人眼能够感 ...

  2. iOS开发那些事--性能优化–内存泄露问题的解决(转)

    内存泄漏问题的解决 内存泄漏(Memory Leaks)是当一个对象或变量在使用完成后没有释放掉,这个对象一直占有着这块内存,直到应用停止.如果这种对象过多内存就会耗尽,其它的应用就无法运行.这个问题 ...

  3. iOS开发系列--Swift进阶

    概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...

  4. iOS开发系列--通知与消息机制

    概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...

  5. iOS开发系列--让你的应用“动”起来

    --iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...

  6. iOS开发系列--让你的应用“动”起来

    --iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...

  7. IOS开发系列 --- 核心动画

    原始地址:http://www.cnblogs.com/kenshincui/p/3972100.html 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...

  8. iOS开发系列--让你的应用“动”起来【转载】

    概览 原文链接:http://www.cnblogs.com/kenshincui/p/3972100.html 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...

  9. iOS开发系列--通知与消息机制--转

    来自:http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户 ...

随机推荐

  1. Robot Framework 快速入门_英文版

    Copyright © Nokia Siemens Networks 2008 Licensed under the Apache License, Version 2.0 Table of Cont ...

  2. ASP.NET Core Identity 配置 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Identity 配置 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Identity 配置 上一章节我们简单介绍了下 Id ...

  3. 图片处理拓展篇 : 图片转字符画(ascii)

    首先要明确思路, 图片是由像素组成的, 不同的像素有不同的颜色(rgb), 那么既然我们要转化为字符画, 最直接的办法就是利用字符串来替代像素, 也就是用不同的字符串来代表不同的像素. 另外图片一般来 ...

  4. DLL编写与调用全解

    DLL编写与调用全解 DELPHI学习   2008-12-23 22:52   阅读8   评论0   字号: 大  中  小 第一章 为什么要使用动态链接库(DLL) top 提起DLL您一定不会 ...

  5. 简单易用的MongoDB

    从我第一次听到Nosql这个概念到如今已经走过4个年头了,但仍然没有具体的去做过相应的实践.最近获得一段学习休息时间,购买了Nosql技术实践一书,正在慢慢的学习.在主流观点中,Nosql大体分为4类 ...

  6. 零元学Expression Blend 4 - Chapter 4元件重复运用的观念

    原文:零元学Expression Blend 4 - Chapter 4元件重复运用的观念 本章将教大家Blend元件重复运用的观念,这在Silverlight设计中是非常重要的,另外加码赠送渐层工具 ...

  7. ArrayList(1.8)

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  8. How to setup Assigned Access in Windows 10 (Kiosk Mode) 设置分配的访问权限(Kiosk模式)

    Let’s say you’re building some sort of ingenious mechanical contraption to be displayed in public th ...

  9. GNU自动化工具使用全过程详解,以及在线手册

    [root@localhost test3]# cat add.h#ifndef _ADD_H_#define _ADD_H_ extern int add(int, int); #endif [ro ...

  10. Linux下卸载QT SDK

    unbuntu下卸载QT方法一:you can remove it like this, those developers should add this somewhere ! like next ...