1.AutoLayout相关的几个易混淆的方法
setNeedsLayout
layoutIfNeeded
layoutSubViews
setNeedsUpdateConstraints
updateConstraitsIfNeed
updateConstraints
子视图在界面上的显示大概经过了:更新约束-通过约束依赖关系得到具体的frame-展示到界面。上面几个是和autolayout相关的方法,有必要大概了解一下这些方法具体是怎么用的以及在什么情况下触发。
1.[layoutView setNeedsUpdateConstraints]:告诉layoutView需要更新约束,在下次计算或者更新约束会更新约束
2.[layoutView updateConstraintsIfNeeded]:告诉layoutView立即更新约束,
3.updateConstraints:系统更新约束的实际方法
总结上面的3点就是,setNeedsUpdateConstraints
确保了在将来某一时刻调用updateConstraintsIfNeeded
之后会接着调用updateConstraints
,从而达到更新view的约束的目的。但是要注意的是,如果仅仅单独调用2,不一定能够保证会调用updateConstraints
,因为如果view上的约束是没有变动的且没有标记需要update的,这时就不会调用updateConstraints
。
4.[layoutView setNeedsLayout]:告诉layoutView页面需要更新,但不立即执行
5.[layoutView layoutIfNeeded]:告诉layoutView页面布局立即更新
6.layoutSubviews:系统重写布局的实际方法
总结以上3点,setNeedsLayout
确保了在将来某个时刻通过调用layoutIfNeeded
之后会调用系统的layoutSubviews
,从而重写对view重新布局。同样的如果单独调用5,不一定能够保证调用layoutSubviews
。[注:笔者写了个demo发现,调用setNeedsLayout
会直接调用layoutSubviews
]。如果想要每次都能立即更新布局,那就要把两个方法一起用,同样也适用于1和2。
系统调用layoutSubViews
时,就会调用updateConstraintsIfNeeded
,通过更新约束,用superView到subView的层次顺序,来计算frame,反向确定布局。
stackoverflow上有关于上面几个方法的深入解答并分享了作者的实用经验:
- 如果仅想要立即改变约束,调用
setNeedsLayout
- 如果改变view的一些属性(如
offsets
)可能会导致布局的改变,那么调用setNeedsUpdateConstraints
,更多的时候后面需要加setNeedsLayout
。 - 如果想要立即改变布局,如会形成新的frame,那么需要在调用
layoutIfNeeded
。