layoutSubview的坑和drawRect分析

LayoutSubview使用中的坑


我们调用layoutsubview去刷新布局的方法是 [self.button setNeedsLayout];  这个方法是异步的,我们来看一下打印结果:


layoutSubview的坑和drawRect分析_第1张图片
1.1


layoutSubview的坑和drawRect分析_第2张图片
1.2

为什么是异步的呢?

因为runloop,这里涉及到runloop的源码分析,这篇文章暂不展开分析,后面会写一篇关于runloop源码分析的文章。这里只需要知道:刷新布局的操作被标记,被runloop放到一下个循环中执行(试想一下,如果同步,那么我有多个view的setNeedsLayout要执行的情况下,性能开销相对比较大)runloop在下一个循环中处理所有的本次循环标记的刷新布局操作。

如何同步?


layoutSubview的坑和drawRect分析_第3张图片
1.4
layoutSubview的坑和drawRect分析_第4张图片
1.5

setNeedsLayout

layoutIfNeeded

只需要这两句一起执行



drawRect分析

CGContextRef context = UIGraphicsGetCurrentContext();

当我们在drawrect中想要绘画内容时,首先会获取我们常说的“上下文”

那么这个上下文是什么呢?

这里我们先来看一下这两句代码

UIGraphicsPopContext();

看一下这句代码的描述


layoutSubview的坑和drawRect分析_第5张图片
1.6

从堆栈顶部删除当前图形上下文,恢复先前的上下文。

使用此功能可以平衡对UIGraphicsPushContext函数的调用。

可以从应用程序的任何线程调用此函数。

我们的图形上下文,是存放在系统的一个专门用来存放上下的堆栈中,系统在drawrect方法中,会将此view的上下文推到这个堆栈中。所以,在drawrect中,获取当前上下文,可以获取到和这个view所关联的上下文,继而操作。我们做一个小实验:


layoutSubview的坑和drawRect分析_第6张图片
layoutSubview的坑和drawRect分析_第7张图片
layoutSubview的坑和drawRect分析_第8张图片

可以看到,只有在view的drawrect方法中,存放上下文的栈才会有当前上下文,也证实了 系统在drawrect方法中,会将此view的上下文推到这个堆栈中   这个结论

UIGraphicsPushContext(nil);

这句代码,则是将某个上下文,推到存放上下文的栈里。

正常情况下,我们不会调用这两句代码,在drawrect中我们就可以获取到当前上下文,不会pop / push

那么context 上下文,影响的是什么呢?

影响的是CALayer

 我们在上下文中的操作,都会渲染到当然view的layer中



延伸1:view和layer的关系是什么

简而言之:我们屏幕上所看到的视觉效果,是CAlayer所展现出来的。而view只是负责管理CAlayer的,UIView是继承UIResponder的,是用来负责响应交互的。

延伸2:IB_DESIGNBLE

一个有意思的可视化:


layoutSubview的坑和drawRect分析_第9张图片
layoutSubview的坑和drawRect分析_第10张图片
layoutSubview的坑和drawRect分析_第11张图片

可以在xib中看到所修饰的view的当前calayer的层次,也就是说在这个view上加个button,再在button的drawrect中绘制,是看不到的。


正在学习~有问题请指出!!多谢~~~~~~~



你可能感兴趣的:(layoutSubview的坑和drawRect分析)