iOS开发系列之性能优化(上)

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

一、卡顿原理

要了解卡顿原理,须要对帧缓冲区、垂直同步、CPU 和 GPU 几个词进行一下了解,而后综合起来,就能够获得卡顿的答案。本篇我就按照本身的理解来进行描述,若有不当,欢迎指正。ios

1.一、帧缓冲区

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

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

1.二、垂直同步 (VSync)

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

1.三、CPU (中央处理器)

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

1.四、GPU (图形处理器)

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

1.五、卡顿原理

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

16毫秒后,预备仓库转正,系统开始读取仓库里的数据,若是这个时候,仓库中的数据尚未准备好,那么系统就会发脾气,放弃读取仓库中的数据。异步

那么这个时候,由于系统的宁缺毋滥,致使了显示器上显示的仍是上一帧画面,就形成了卡顿的效果。布局

二、性能优化

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

2.一、CPU 工做之正式对象的建立和销毁

  • UITableViewCell 和 UICollectionViewCell 的复用,能够减小 cell 的建立操做;

  • 尽可能使用轻量级的对象,能够减小对象的建立时间,好比在不须要事件处理的场景里,使用CALayer 比 UIView 会更加合适;

  • 表情键盘使用 UICollectionViewCell 代替 UIButton,能够减小对象的建立操做;

  • 对象不涉及UI操做,放到后台线程建立;

  • 性能要求严格的界面,storyborad的资源消耗>代码建立;

  • 推迟对象建立的时间,对象放到多个任务中,好比懒加载;

2.二、CPU 工做之对象属性的调整

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

2.三、CPU 工做之布局计算

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

  • frame 计算好,较少没必要要的修改;

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

2.四、CPU 工做之文本的计算和排版

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

  • CoreText 对象占用内存较少,当显示大量文本时,能够用 CoreText 对文本异步绘制;

2.五、CPU 工做之图片的格式转换和解码

  • 在后台线程先把图片绘制到 CGBitmapContext 中,而后从 Bitmap 直接建立图片;

2.六、CPU 工做之图像的绘制

  • UITableViewCell 滑动减速的时候才加载图片,能够参考这个demo

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

2.七、GPU 工做之渲染

  • 尽可能不要让图片和视图的大小超过 GPU 纹理尺寸上限:4096×4096,否则图片还须要通过 CPU 的处理;

  • 尽可能减小视图数量和层次,并设置视图为不透明,UIView 的不透明属性 (opaque) 默认为 YES,通常设置背景颜色便可;CALayer 的不透明属性 (opaque) 默认为 NO,须要设置为 YES;

  • CALayer 的 border、圆角、阴影、遮罩,一般会触发离屏渲染,尽可能少用,圆角属性可使用 CoreGraphics 绘制或使用圆角图片代替,关于离屏渲染的知识,具体能够参考这篇文章:iOS 图形性能优化;

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

最后郑重声明,本篇里只是记录一下个人我的理解和代码实践,资料大量参考了这篇文章:iOS 保持界面流畅的技巧,做者是写出了 YYKit 框架的大牛,想要深刻学习的朋友请移步。

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

相关文章
相关标签/搜索