iOS面试题集合

UIView 的渲染过程

2020-04-07  本文已影响0人  若水water

标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,在下一轮runloop结束前刷新,对于这一轮runloop之内的所有布局和UI上的更新只会刷新一次,layoutSubViews一定会被调用。

如果有需要刷新的标记,立即调用layoutSubViews进行布局(如果没有标记,不会调用layoutSubViews)

注意:

[self setNeedsLayout];
[self layoutIfNeeded];

和setNeedsLayout一样是异步执行的,此方法会调用drawRect方法。

layoutSubviews 以下情况会调用
drawRect 在以下情况下会被调用
drawRect方法使用注意点

这是一个UIView的方法。意思是调整和移动view 和view内部子视图的大小和位置。当你想要调整当前视图,以便他使用最合适的空间的时候用这个方法。特定的视图会根据内部需要进行尺寸调整。在特定条件下,如果view没有父视图,他会根据屏幕的bounds来进行调整。如果你需要view根据父视图来调整大小,就需要将view添加到父视图中取。
其实说白了,就是让当前视图以最适合的尺寸来调整大小,参照物是父视图尺寸,没有父视图就用屏幕bounds。
你不可以直接对这个方法进行重写,如果你需要改变视图的默认尺寸,你可以重写- (CGSize)sizeThatFits:(CGSize)size这个方法。在这个方法里面可以进行一些必要的计算并在这个方法中对计算的结果进行返回。

要求视图去计算和返回一个最适合的指定尺寸的尺寸。
传入:是一个指定的最适合的尺寸
返回:是view的子view最适合的尺寸
默认实现是返回view自己的size
例如:

应用场景

使用注意点:

view的绘制渲染机制和runloop有什么关系

堆栈信息:


image.png
底层实现

在操作UI时,比如改变了frame,更新了UIView/CALayer的层次时,或者手动调用了UIView/CALayer的setNeedsLayout/setNeedsdisplay 方法后,这个UIView/CALayer就被标记为待处理,并被提交到一个全局的容器中去。苹果注册了一个Observer 来监听runloop的BeforeWaiting(即将进入休眠)和Exit(即将退出)事件,回调一个函数:
_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv(),这个函数会遍历所有待处理的UIView/CAlayer,以执行实际的绘制和调整,并更新UI界面。

列表卡顿,到底是什么引起的

iOS的mainrunloop 是一个60fps(每秒刷新60次)的回调,也就是说每16.7ms 会绘制一次屏幕,这个时间段内要完成view的缓冲区创建,view内容的绘制(如果重写了drawRect),这些CPU的工作。然后将这个缓冲区交给GPU渲染,这个过程又包括多个view的拼接(compositing)和纹理的渲染(Texture)等,最终显示在屏幕上。因此,如果16.7ms 内完不成这些操作,比如CPU做了太多的工作,或者view层次过于多,图片过于大,导致GPU压力太大,就会导致’卡‘的显现,也就是丢帧。

我们经常在drawRect方法里绘制代码,该方法是谁调用的 何时调用的?
drawrect方法内为何第一行代码总要获取图形的上下文

每一个UIView都有一个layer,每一个layer都有个content,这个content指向的是一块缓存,叫做backing store,当UIView被绘制时,CPU执行drawRect,通过context 将数据写入backing store,当backing store写完后,通过render server 交给GPU去渲染,将backing store中的bitmap数据显示在屏幕上,所以在drawRect方法中,要首先获取context。

image.png
视图绘制过程
view的渲染机制 和GPU之间的关系

GPU处理的单位是texture
基本上我们控制GPU都是通过open GL来完成,但是从bitmap到texture之间需要一座桥梁,core animation正好充当了这个角色,Core Animation对open GL 的api 有一层封装,当我们的要渲染的layer已经有了bitmap content的时候,这个content一般来说是一个CGImageRef,CoreAnimation会创建一个open GL的texture,并将CGImageRef(bitmap)和这个texture绑定,通过textureID来标识。
这个对应关系建立起来之后,剩下的任务就是GPU如何将texture渲染到屏幕上了。

从硬件的角度来看

GPU的工作模式:CPU将准备好的bitmap放到ram里,GPU去搬这块内存到VRAm(显存的一种)中处理。而这个过程GPU所能承受的极限大概在16.7ms完成一帧的处理。所以最开始提到的60fps其实就是GPU能处理的最高频率。

总结视图的渲染过程
上一篇 下一篇

猜你喜欢

热点阅读