1. 事件传递机制和响应者链条
学习链接
响应者对象(UIResponder)
继承了UIResponder的对象
UIApplication
UIViewController
UIView
UIResponder内部提供了以下方法来处理事件触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
响应者链的事件传递过程:
1>如果当前view是控制器的view,那么控制器就是上一个响应者,事件就传递给控制器;如果当前view不是控制器的view,那么父视图就是当前view的上一个响应者,事件就传递给它的父视图
2>在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
3>如果window对象也不处理,则其将事件或消息传递给UIApplication对象
4>如果UIApplication也不能处理该事件或消息,则将其丢弃
2. UI绘制原理
学习链接
UIView和CALayer的关系
UIView负责处理相应事件,CALayer负责显示.六大设计原则的单一原则
iOS的mainRunloop是一个60fps的回调,也就是说每16.7ms会绘制一次屏幕,这个时间段内要完成view的缓冲区创建,view内容的绘制(如果重写了drawRect),这些CPU的工作。然后将这个缓冲区交给GPU渲染,这个过程又包括多个view的拼接(compositing),纹理的渲染(Texture)等,最终显示在屏幕上。
保证CPU和GPU的完成工作在16.7ms之内
3. 异步绘制原理
AsyncDisplayKit
UI 线程中一旦出现繁重的任务就会导致界面卡顿,这类任务通常分为3类:排版,绘制,UI对象操作。
排版通常包括计算视图大小、计算文本高度、重新计算子式图的排版等操作。
绘制一般有文本绘制 (例如 CoreText)、图片绘制 (例如预先解压)、元素绘制 (Quartz)等操作。
UI对象操作通常包括 UIView/CALayer 等 UI 对象的创建、设置属性和销毁。
其中前两类操作可以通过各种方法扔到后台线程执行,而最后一类操作只能在主线程完成,并且有时后面的操作需要依赖前面操作的结果 (例如TextView创建时可能需要提前计算出文本的大小)。ASDK 所做的,就是尽量将能放入后台的任务放入后台,不能的则尽量推迟 (例如视图的创建、属性的调整)
4. 流式页面的性能优化
从CPU层面
创建对象.创建对象会分配内存,对象过多,比较消耗 CPU 资源 。
1、尽量用轻量的对象代替重量的对象,可以对性能有所优化。比如 CALayer 比 UIView 要轻量,如果不需要响应触摸事件,用 CALayer 显示会更加合适。如果对象不涉及 UI 操作,则尽量放到后台线程去创建,但如果是包含了 CALayer 的控件,都只能在主线程创建和操作。
2、通过 Storyboard 创建视图对象时,其资源消耗会比直接通过代码创建对象要大非常多。
3、使用懒加载,尽量推迟对象创建的时间,并把对象的创建分散到多个任务中去。
调整对象
调整对象视图层级
尽量的避免或者减少调整视图层次、添加和移除视图。
调整对象布局计算
不论通过何种技术对视图进行布局,其最终都会落到对 UIView.frame/bounds/center 等属性的调整上。对这些属性的调整非常消耗资源,所以尽量提前计算好布局,如果一次性可以调整好对应属性,就不要多次、频繁的计算和调整这些属性
调整对象文本计算
用 [NSAttributedString boundingRectWithSize:options:context:] 来计算文本宽高,用 -[NSAttributedString drawWithRect:options:context:] 来绘制文本,记住放到后台线程进行以避免阻塞主线程。
进行预处理,预排版等操作
异步绘制
从GPU层面
尽量避免离屏渲染
5. 离屏渲染
学习链接
起源于GUP,在当前屏幕的缓冲区外新建缓冲区进行渲染操作.因为涉及新开辟内存,渲染完成还要管线合成,对性能损耗比较大.
一种特殊的“离屏渲染”方式: CPU渲染。
如果我们重写了drawRect方法,并且使用任何Core Graphics的技术进行了绘制操作,就涉及到了CPU渲染。整个渲染过程由CPU在App内 同步地完成,渲染得到的bitmap最后再交由GPU用于显示。
设置了以下属性时,都会触发离屏绘制:
shouldRasterize(光栅化)
masks(遮罩)
shadows(阴影)
edge antialiasing(抗锯齿)
group opacity(不透明)
复杂形状设置圆角等
渐变
iOS 9.0 之前UIimageView跟UIButton设置圆角都会触发离屏渲染
iOS 9.0 之后UIButton设置圆角会触发离屏渲染,而UIImageView里png图片设置圆角不会触发离屏渲染了,如果设置其他阴影效果之类的还是会触发离屏渲染的
UIimageView圆角设置不会导致离屏渲染两种方法
1 切割图片
2 画圆角给图片遮罩上
网友评论