UIKit

iOS-View绘制

2019-07-30  本文已影响0人  JerrySi

关于渲染机制是很多开发人员容易忽略掉的,很多时候认为会用就可以了,其实知道底层渲染机制特别是渲染的时间点对我们是很有帮助的。

这里有篇文章写的不错:https://blog.csdn.net/yangyangzhang1990/article/details/52452707/

本文对该文章结合自己的经验进行结论整理。


绘制流程

当在操作 UI 时,比如改变了 Frame、更新了 UIView/CALayer 的层次时,或者手动调用了 UIView/CALayer 的 setNeedsLayout/setNeedsDisplay方法后,这个 UIView/CALayer 就被标记为待处理,并被提交到一个全局的容器去。

苹果注册了一个 Observer 监听 BeforeWaiting(即将进入休眠) 和 Exit (即将退出Loop) 事件,回调去执行一个很长的函数:_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()。这个函数里会遍历所有待处理的 UIView/CAlayer 以执行实际的绘制和调整,并更新 UI 界面。


drawRect什么时候会被调用?

前提:如果UIView没有设置rect大小,将直接导致drawRect不被调用。

1. setNeedsDisplay:需要重绘,异步调用drawRect

2. - (void)setNeedsDisplayInRect:(CGRect)rect:需要局部重绘,同样会异步调用drawRect

3. 通过设置view的contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect。

4. 调用sizeThatFits会触发调用drawRect。

drawRect性能优化原则:缩小绘制区域,降低重绘频率


layoutSubviews什么时候会被调用?

前提:如果UIView没有设置rect大小,将直接导致layoutSubviews不被调用。

1.调用setNeedsLayout 或者 layoutIfNeeded的时候

2.addSubview的时候。

3.当view的size发生改变的时候。

4.滑动UIScrollView的时候。

5.旋转Screen会触发父UIView上的layoutSubviews事件。


这里顺便说明下setNeedsLayout和layoutIfNeeded区别

1. setNeedsLayout

标记为需要重新布局,不立即刷新,但layoutSubviews一定会被调用,配合layoutIfNeeded立即更新

2. layoutIfNeeded

如果有需要刷新的标记,立即调用layoutSubviews进行布局

3. 用法

如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局。

事实上我们主动调用这2个方法的时候不多,大多数情况是通过约束初始化控件后,要及时得到控件的大小的时候,主动调用下layoutIfNeeded。

上一篇下一篇

猜你喜欢

热点阅读