一个倾向于强化巩固记忆的知识点复习。
在一个 Runloop 处理完事件后,最后进入 Update cycle:
- 更新约束
- 布局:引擎计算视图和子视图的 frame 并布局
- 显示:重绘视图
Step1:更新约束
updateConstraints()
类似于 layoutSubviews 的机制。
只应该在此方法中实现必须要更新的约束,静态的约束应在interface builder、视图的初始化方法或 viewDidLoad() 方法中指定。
不应直接调用,应调用触发方法让系统处理
自动标记约束发生变化,在下一个周期会触发 updateConstraints 的行为:
- 设置/解除约束
- 更改约束优先级
- 从视图层级 (view hierarchy) 中移除视图
setNeedUpdateConstraints()
类似于 setNeedsLayout 的机制,手动标记发生变化,下周期调用 updateConstraints 更新
updateConstraintsIfNeeded()
类似于 layoutIfNeeded 的机制,检查视图的约束是否被标记发生变化,如有变化立即调用 updateConstraints
invalidateIntrinsicContentSize()
设置一个标记表示这个视图的 intrinsicContentSize 已经过期,需要在下一个布局阶段重新计算。
视图的 intrinsicContentSize:视图根据自己内容得到的自然尺寸,通常由包含元素的约束约定,也可以自定义
Step2:布局视图
layoutSubviews()
处理对视图及其所有子视图的重新定位和大小调整 会调用子视图的 layoutSubviews,开销很大
不应直接调用,应调用触发方法让系统处理
自动标记视图的布局发生变化,在下一个周期会触发 layoutSubviews 的行为:
- 通过 setFrame 改变视图的 bounds(不仅是位置)
- add subview
- UIScrollView 的滚动(layoutSubviews 会在 UIScrollView 和它的父 view 上被调用)
- 旋转设备:调用当前 controller 的 self.view 的 layoutSubviews
- 更新视图的 constraints
setNeedsLayout()
手动标记该视图的布局发生变化,在下一个周期调用 layoutSubviews 更新
layoutIfNeeded()
检查视图的布局是否被标记发生变化,如有变化立即调用 layoutSubviews
Step3:绘制
drawRect()
类似于 layoutSubviews 的机制,但不会触发对子视图方法的调用
不应直接调用,应调用触发方法让系统处理
自动标记视图显示发生变化,在下一个周期会触发 drawRect 的行为:
- 改变视图的 bounds
setNeedsDisplayInRect()
类似于 setNeedsLayout 的机制,手动标记发生变化,下周期调用 drawRect 更新
显示方法没有类似 layoutIfNeeded 的方法