了解屏幕成像的原理。
有一个电子枪然后在很多横轴方向上 发射电子,不同横轴的电子枪根据显示器中的硬件时钟产生一系列的定时信号,以此来让电子以不同的时间发射出去 这些电子一瞬间的运动形成了一帧动画。
CPU优化:
1.文本计算优化
如果一个界面中包含大量文本(比如微博微信朋友圈等),文本的宽高计算会占用很大一部分资源,并且不可避免。如果你对文本显示没有特殊要求,可以参考下 UILabel 内部的实现方式:用 [NSAttributedString boundingRectWithSize:options:context:] 来计算文本宽高,用 -[NSAttributedString drawWithRect:options:context:] 来绘制文本。尽管这两个方法性能不错,但仍旧需要放到后台线程进行以避免阻塞主线程。
如果你用 CoreText 绘制文本,那就可以先生成 CoreText 排版对象,然后自己计算了,并且 CoreText 对象还能保留以供稍后绘制使用。
2.图片的解码
当用 UIImage 或 CGImageSource 的那几个方法创建图片时,图片数据并不会立刻解码。图片设置到 UIImageView 或者 CALayer.contents 中去,并且 CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码。这一步是发生在主线程的,并且不可避免。如果想要绕开这个机制,常见的做法是在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片。目前常见的网络图片库(Kingfisher)都自带这个功能。
关于Bitmap:我们可以将bitmap理解为一个点阵图或者是一个数组,其中的每个元素都是一个像素信息,假设对于一个32位RGBA图像来说,则每个元素包含着三个颜色组件(R,G,B)和一个Alpha组件,每一个组件占8位(8bite = 1byte = 32 / 4)。这些像素集合起来就可以表示出一张图片。
关于CGImageSource:一种不透明类型,用于从 URL、数据对象或数据使用者读取图像数据。
func CGImageSourceCreateWithURL(CFURL, CFDictionary?) -> CGImageSource?
创建从 URL 指定的位置读取的图像源。
3.UITableView自动布局优化
( 1 )适用于iOS8以后,自上而下添加约束后:
// 设置预估行高, 必须要写, 否则打印垃圾log日志, 提示约束冲突,随便写一个值就行了
view.estimatedRowHeight = 80
// 自动计算行高
view.rowHeight = UITableView.automaticDimension
( 2 )第三方库 UITableView+FDTemplateLayoutCell
UITableView+FDTemplateLayoutCell主要是利用Runloop在空闲状态下后台计算tableviewcell的高度并缓存起来。然后在使用的时候就直接从缓存中去,这里都放在一个数组里存在内存。
// 实现计算高度的方法
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.fd_heightForCell(withIdentifier: "result",cacheBy: indexPath, configuration: { cell in
// 配置cell的数据
//和 cellForRowAt 中内容一样即可
(cell as! TableViewCell).Label.text = texts[indexPath.row % 12]
})
}
GPU优化:
4.图形的生成。
CALayer 的 border、圆角、阴影、遮罩(mask),CASharpLayer 的矢量图形显示,通常会触发离屏渲染(offscreen rendering),而离屏渲染通常发生在 GPU 中。当一个列表视图中出现大量圆角的 CALayer,并且快速滑动时,可以观察到 GPU 资源已经占满,而 CPU 资源消耗很少。这时界面仍然能正常滑动,但平均帧数会降到很低。为了避免这种情况,可以尝试开启 CALayer.shouldRasterize 属性,但这会把原本离屏渲染的操作转嫁到 CPU 上去。对于只需要圆角的某些场合,也可以用一张已经绘制好的圆角图片覆盖到原本视图上面来模拟相同的视觉效果。最彻底的解决办法,就是把需要显示的图形在后台线程绘制为图片,避免使用圆角、阴影、遮罩等属性。
5. ASDK
ASDK 认为,阻塞主线程的任务,主要分为上面这三大类。文本和布局的计算、渲染、解码、绘制都可以通过各种方式异步执行,但 UIKit 和 Core Animation 相关操作必需在主线程进行。ASDK 的目标,就是尽量把这些任务从主线程挪走,而挪不走的,就尽量优化性能。
参考:
iOS 保持界面流畅的技巧 | Garan no dou