iOS-Auto Layout[7]-Changing Constraints

一般情况下,Constraints都是在设计阶段就计算完成,如果需要在运行时改变Constraints,最好是在状态发生变化时,例如按钮被点击。

The Deferred Layout Pass

AutoLayout并不会直接改变View的Frames,而是通过Layout Pass的方式来进行更新。Layout Pass更新layout的Constraints,然后计算出所有View的frames来进行更新。

调用以下两个方法之一来进行Layout Pass

1
2
setNeedsLayout
setNeedsUpdateConstraints

The Deferred Layout Pass将会在View结构树中传递两个Pass:

Update Pass

Update Pass将会更新Constraints,系统将会在所有ViewController中调用方法:

1
updateViewConstraints

并在所有的View中调用方法:

1
updateConstraints

如果需要进一步优化性能,可以自定义updateConstraints方法。自定义时,需要注意:

  • 不要在updateConstraints方法中调用setNeedsUpdateConstraints方法,否则会发生死锁;
  • 调用super方法;
  • updateConstraints应该尽可能地高效;
  • 不要deactivate所有Constraints,只reactivate需要更新的constraint即可;
  • 只改变需要变化的View的Constraints。

Layout Pass

Layout Pass将会更新Frames,系统将会在所有ViewController中调用方法:

1
viewWillLayoutSubviews

并在所有的View中调用方法:

1
layoutSubviews

如果需要进一步优化性能,可以自定义这两个方法。自定义时,需要注意:

  • 不要调用setNeedsUpdateConstraints和setNeedsLayout方法,否则会发生死锁;
  • 调用super方法;
  • 如果需要invalidate一个View的layout,记得在调用super方法之前,并确认该View是处于SubTree中。