UI视图及UITableView流畅性优化

一.离屏渲染

1. 在屏渲染和离屏渲染
  • 在屏渲染是指在当前用于显示的屏幕缓冲区进行GPU渲染操作
  • 离屏渲染是指在当前屏幕缓冲区以外新开辟一个缓冲区进行GPU渲染

当我们指定了UI视图的某些属性标记为它在位域合成之前不能用于当前屏幕上面直接显示的时候就会触发离屏渲染,当前屏幕缓冲区以外新开辟一个缓冲区进行GPU渲染。

2.何时触发离屏渲染

  • 圆角(和maskToBounds一起使用时)
  • 图层蒙版
  • 阴影
  • 光栅化

3.为何要避免离屏渲染

  • 创建新缓冲区
  • 上下文切换,当前屏幕缓冲区(On-Screen)和离屏缓冲区(Off-Screen)来回切换,切换上下文付出的代价较大。
  • 在进行离屏渲染时会加大GPU的工作时间,使CPU+GPU的的时间大大超过一帧所用的时间,由此导致掉帧卡顿,所以要避免离屏渲染。

二.UITableView流畅性优化

1.避免主线程阻塞

  • 尽量在子线程完成对象的创建调整销毁工作,进行预排版,图片解码等操作

2.避免频繁的对象创建

  • 对象的创建会发送内存分配、属性调整等。
  • 尽量用轻量的对象代替重量的对象。比如CALayer代替UIView。
  • 多利用缓存思想,对象创建后缓存起来,需要的时候再拿出来用。合理利用内存开销,减少CPU开销。

3.减少对象的属性赋值操作

  • UIView的frame/bounds等属性的赋值操作,会产生比较大的CPU消耗。

4.异步绘制

  • UIKit和CoreAnimation相关操作必须在主线程中进行,其它的可以在后台线程异步执行
  • 比方说:为一个UIImageView设置image
imageView.image = image;

以上代码必须在主线程进行,但这个image的绘制过程,可以在异步线程做

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    CGContextRef ctx = CGBitmapContextCreate(...);
    // 绘图
    CGImageRef imgRef = CGBitmapContextCreateImage(ctx);//位图
    UIImage *image = [UIImage imageWithCGImage:imgRef];//转成UIImage
    dispatch_async(dispatch_get_main_queue(), ^{
        //回到主线程
        imageView.image = image;//设置imageView的image
    });
});

就是尽量把需要显示的内容,在异步线程绘制,绘制好后再通知主线程显示。

5.简化视图结构

GPU在绘制图像前,会把重叠的视图进行混合,视图结构越复杂,这个操作就越耗时,如果存在透明视图,混合过程会更加复杂。

  • 尽量避免复杂的图层结构
  • 少使用透明的视图
  • 不透明的视图,设置opaque = YES
  • 把视图异步绘成一张图

6.减少离屏渲染

三.UIView的绘制原理

UIView调用setNeedsDisplay方法后,实际上并没有发生当前视图的绘制工作,而是在之后的某一时机进行绘制工作,为什么会在之后的某一时机进行绘制工作呢?
当UIView调用setNeedDisplay之后,系统会调用view对应layer的 setNeedsDisplay方法,相当于在当前layer上打上了一个脏标记,然后会在当前runloop即将结束的时候调用CALayer的display方法,才会真正的进入当前视图的绘制流程当中,所以视图的绘制时机,是在当前runloop即将结束的时候才会开始.
CALayer的display方法的内部实现,首先会判断layer的delegete是否响应display方法,如果代理不响应就会进入到系统的绘制流程当中,如果响应,实际上就为我们提供了异步绘制的接口,这样就构成了UIView的绘制原理

系统的绘制流程
首先CALayer会在内部创建一个backing store(CGContextRef),我们一般在drawRect中可以通过上下文堆栈当中拿到当前栈顶的context.然后layer判断是否有代理,如果没有代理会调用layer的drawInContext方法,如果实现了代理就会调用delegete的drawLayer:inContext方法,这是在发生在系统内部当中的,然后在合适的时机给予回调方法,也就是View的drawRect方法.可以通过drawRect方法做一些其他的绘制工作.然后无论哪两个分支,都有calayer上传backing store (最终的位图)到CPU.然后结束系统的绘制流程.

异步绘制

怎么进行异步绘制呢,其实就是基于系统给我们开的口子layer.delegate,如果遵从或者实现了displayLayer方法,我们就可以进入到异步绘制流程当中,在异步绘制的过程当中

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

推荐阅读更多精彩内容