iOS界面优化原理及解决方案

本文内容是参考文章:http://www.cocoachina.com/ios/20151130/14477.html

*写本篇文章的目的为了总结和梳理上面那篇文章(YYKit的作者写的)的知识点,我并不是想秀~~~~

一.屏幕显示图像的原理

基本上所有的显示器都是遵循CRT显示器原理,在显示一帧图像的时候大致是一把电子枪经过从左至右、从上到下的顺序进行扫描,扫描完成后显示器就会显示完整的一帧画面。

总的来说,CPU、GPU、显示器的协作方式大致是下图方式:

借用一下~~嘻嘻

1、CPU计算显示内容传递给GPU。

2、GPU渲染完成后将这一帧的内容放到帧缓冲区。(这里有两个帧缓存区,GPU会根据信号来回切换)

3、视频控制器取出缓冲区的内容并转换传递给显示器。(这里视频控制器是通过垂直水平信号VSync获取缓冲区数据)

4、显示器显示完成后并发送VSync信号给GPU。

5、跳到第二步进行循环。

二、手机界面卡顿的原因

显示器在显示完一帧之后,发送垂直同步信号到CPU、GPU,如果这时候CPU和GPU在信号时间内没有完成计算或渲染内容,也就是缓存区没有内容可取,此时显示器还是会显示上一帧的内容,这时手机界面就会给人以卡顿的感觉。这也就是卡顿的主要原因了。

此时如果要对界面优化,主要就是针对CPU和GPU资源消耗进行优化了。

也许有人不知道CPU核GPU的区别(我就是其中一个),我查了下。CPU又叫中央处理器,GPU叫图形处理器。

    ——CPU比较适合处理复杂的逻辑控制,通用性更强,能够处理很多不同的数据类型。

    ——GPU适合图像处理和大规模并发计算。

它们的内部结构大概是这样(继续偷图)

想了解更多点击这里

三、CPU资源消耗解决方案

在程序运行中比较消耗CPU资源的主要是:

1、对象创建

    消耗资源:

            ——对象的创建会分配内存、调整属性、文件操作。

    优化方案:

            ——尽量使用轻量的对象代替重量级的对象(如:轻量级CALayer、重量级UIView)

            ——尽量推迟对象的创建时间,并把对象的创建分散到多个任务中去(CALayer、UIVIew的创建操作只能在主线程)。

            ——如果对象可以复用并且复用的代价比释放重新创建要小就尽量复用。

2、对象调整

             消耗资源:

                    ——CALayer内部并没有属性,在调用属性方法时候,它内部是通过运行时resolveInstanceMethod为对象临时添加一个方法,并把对应的属性保存到内部的字典里面,同时还会通知代理、创建动画等等。所以在使用UIView的显示相关属性时其实都是CALayer属性映射来的。

            优化方案:    

                    ——尽量减少显示相关属性不必要的修改。

                    ——尽量避免视图层次调整、添加和移除。

3、对象销毁

            消耗资源:

                    ——只有当一个对象容器持有大量对象时,销毁时的资源消耗比较明显。

            优化方案:    

                    ——如果对象可以放到后台线程去释放,就尽量放到后台去释放。

4、布局计算

               消耗资源:

                    ——不论用什么技术对视图进行布局,终究还是改变UIVIew的frame/bounds/center 等属性的调整。

            优化方案:    

                    ——在后台线程提前计算好布局,在需要时一次性计算调整好对应属性,不要多次、频繁的计算和调整。

5、Autolayout

               消耗资源:

                    ——不论用什么技术对视图进行布局,终究还是改变UIVIew的frame/bounds/center 等属性的调整。

            优化方案:    

                    ——在后台线程提前计算好布局,在需要时一次性计算调整好对应属性,不要多次、频繁的计算和调整。

6、文本计算

            消耗资源:

                    ——如果一个界面中包含大量文本,文本的宽高计算会占用很大一部分资源,并且不可避免。

            优化方案:    

                    ——如果对文本显示没有特殊要求,可以参考下 UILabel 内部的实现方式:用 [NSAttributedString boundingRectWithSize:options:context:] 来计算文本宽高,用 -[NSAttributedString drawWithRect:options:context:] 来绘制文本。尽管这两个方法性能不错,但仍旧需要放到后台线程进行以避免阻塞主线程。

                     ——如果用 CoreText 绘制文本,那就可以先生成 CoreText 排版对象,然后自己计算了,并且 CoreText 对象还能保留以供稍后绘制使用。

7、文本渲染

            消耗资源:

                    ——屏幕上能看到的所有文本内容控件,包括 UIWebView,在底层都是通过 CoreText 排版、绘制为 Bitmap 显示的。常见的文本控件 (UILabel、UITextView 等),其排版和绘制都是在主线程进行的,当显示大量文本时,CPU 的压力会非常大。

            优化方案:    

                    ——解决方案只有一个,那就是自定义文本控件,用 TextKit 或最底层的 CoreText 对文本异步绘制。CoreText 对象创建好后,能直接获取文本的宽高等信息,避免了多次计算(调整 UILabel 大小时算一遍、UILabel 绘制时内部再算一遍);CoreText 对象占用内存较少,可以缓存下来以备稍后多次渲染。

8、图片的解码

                消耗资源:

                    ——用 UIImage 或 CGImageSource 的那几个方法创建图片时,图片数据并不会立刻解码。图片设置到 UIImageView 或者 CALayer.contents 中去,并且 CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码。这一步是发生在主线程的,并且不可避免。

            优化方案:    

                    ——在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片。目前常见的网络图片库都自带这个功能。

9、图像的绘制

               消耗资源:

                    ——图像的绘制通常是指用那些以 CG 开头的方法把图像绘制到画布中,然后从画布创建图片并显示这样一个过程。这个最常见的地方就是 [UIView drawRect:] 里面了。

            优化方案:    

                    ——由于 CoreGraphic 方法通常都是线程安全的,所以图像的绘制可以很容易的放到后台线程进行。

四、GPU资源消耗解决方案

1、纹理的渲染

            消耗资源:

                    ——所有的 Bitmap,包括图片、文本、栅格化的内容,最终都要由内存提交到显存,绑定为 GPU Texture。不论是提交到显存的过程,还是 GPU 调整和渲染 Texture 的过程,都要消耗不少 GPU 资源。当在较短时间显示大量图片时(比如 TableView 存在非常多的图片并且快速滑动时),CPU 占用率很低,GPU 占用非常高,界面仍然会掉帧。

                    ——当图片过大,超过 GPU 的最大纹理尺寸时,图片需要先由 CPU 进行预处理,这对 CPU 和 GPU 都会带来额外的资源消耗。

            优化方案:    

                    ——尽量减少在短时间内大量图片的显示,尽可能将多张图片合成为一张进行显示。

                    ——目前来说,iPhone 4S 以上机型,纹理尺寸上限都是 4096x4096,更详细的资料可以看这里:iosres.com。所以,尽量不要让图片和视图的大小超过这个值。

2、视图的混合

            消耗资源:

                    ——当多个视图(或者说 CALayer)重叠在一起显示时,GPU 会首先把他们混合到一起。如果视图结构过于复杂,混合的过程也会消耗很多 GPU 资源。

            优化方案:    

                    ——为了减轻这种情况的 GPU 消耗,应用应当尽量减少视图数量和层次,并在不透明的视图里标明 opaque 属性以避免无用的 Alpha 通道合成。当然,这也可以用上面的方法,把多个视图预先渲染为一张图片来显示。

3、图片的形成

            消耗资源:

                    ——CALayer 的 border、圆角、阴影、遮罩(mask),CASharpLayer 的矢量图形显示,通常会触发离屏渲染(offscreen rendering),而离屏渲染通常发生在 GPU 中。当一个列表视图中出现大量圆角的 CALayer,并且快速滑动时,可以观察到 GPU 资源已经占满,而 CPU 资源消耗很少。这时界面仍然能正常滑动,但平均帧数会降到很低。

            优化方案:    

                    ——可以尝试开启 CALayer.shouldRasterize 属性,但这会把原本离屏渲染的操作转嫁到 CPU 上去。对于只需要圆角的某些场合,也可以用一张已经绘制好的圆角图片覆盖到原本视图上面来模拟相同的视觉效果。最彻底的解决办法,就是把需要显示的图形在后台线程绘制为图片,避免使用圆角、阴影、遮罩等属性。


最后作者推荐了个框架AsyncDisplayKit。该框架对CALayer进行了封装,当使用该框架封装的view时,里面将消耗性能的操作放在后台线程进行处理,并且节省了资源。

但是在平时日常的开发中,一般是没有时间进行优化的,最好是将优化工作放到后期处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容