LayoutSubview使用中的坑
我们调用layoutsubview去刷新布局的方法是 [self.button setNeedsLayout]; 这个方法是异步的,我们来看一下打印结果:
为什么是异步的呢?
因为runloop,这里涉及到runloop的源码分析,这篇文章暂不展开分析,后面会写一篇关于runloop源码分析的文章。这里只需要知道:刷新布局的操作被标记,被runloop放到一下个循环中执行(试想一下,如果同步,那么我有多个view的setNeedsLayout要执行的情况下,性能开销相对比较大)runloop在下一个循环中处理所有的本次循环标记的刷新布局操作。
如何同步?
setNeedsLayout
layoutIfNeeded
只需要这两句一起执行
drawRect分析
CGContextRef context = UIGraphicsGetCurrentContext();
当我们在drawrect中想要绘画内容时,首先会获取我们常说的“上下文”
那么这个上下文是什么呢?
这里我们先来看一下这两句代码
UIGraphicsPopContext();
看一下这句代码的描述
从堆栈顶部删除当前图形上下文,恢复先前的上下文。
使用此功能可以平衡对UIGraphicsPushContext函数的调用。
可以从应用程序的任何线程调用此函数。
我们的图形上下文,是存放在系统的一个专门用来存放上下的堆栈中,系统在drawrect方法中,会将此view的上下文推到这个堆栈中。所以,在drawrect中,获取当前上下文,可以获取到和这个view所关联的上下文,继而操作。我们做一个小实验:
可以看到,只有在view的drawrect方法中,存放上下文的栈才会有当前上下文,也证实了 系统在drawrect方法中,会将此view的上下文推到这个堆栈中 这个结论
UIGraphicsPushContext(nil);
这句代码,则是将某个上下文,推到存放上下文的栈里。
正常情况下,我们不会调用这两句代码,在drawrect中我们就可以获取到当前上下文,不会pop / push
那么context 上下文,影响的是什么呢?
影响的是CALayer
我们在上下文中的操作,都会渲染到当然view的layer中
延伸1:view和layer的关系是什么
简而言之:我们屏幕上所看到的视觉效果,是CAlayer所展现出来的。而view只是负责管理CAlayer的,UIView是继承UIResponder的,是用来负责响应交互的。
延伸2:IB_DESIGNBLE
一个有意思的可视化:
可以在xib中看到所修饰的view的当前calayer的层次,也就是说在这个view上加个button,再在button的drawrect中绘制,是看不到的。