参考资料:
Apple官方AutoLayout资料
iOSエンジニア必見!!iOSのレイアウトで押さえておきたいこと【総集編】

约束调试

当系统检测到autolayout冲突时候
1 定位冲突的约束
2 系统打破一个约束,然后检查是否有冲突,如果有重复之前的步骤
3 在consolo中输出冲突以及打破的约束

如果要调试约束的冲突可以add symbolic breakpoint。

  • 在Symbol中输入UIViewAlertForUnsatisfiableConstraints
  • Action选择Debugger Command
  • 在Action中输入expr -l objc++ -O – [[UIWindow keyWindow] _autolayoutTrace]

这样在console中输入命令可以改变UIView的颜色,输入完后按一下运行的三角按钮

约束冲突

如何去修正冲突的约束?
首先分析什么情况下容易发生约束冲突
1 添加子view的时候
设定子view的translatesAutoresizingMaskIntoConstraints的值为false,
2 提供的空间太小,导致一些view的内容无法正常显示
将一些约束的优先级降低(默认是1000,你可以设置为999),如果发生冲突,这些约束优先会被舍弃。尽量不要设定固定的长度或高度。

模糊布局

含糊不清的layout,具体表现是view可能有多种展示方式。
原因主要有两个
1 缺少某些约束
2 约束发生冲突,冲突的约束优先级相同

关于变更约束

有四种情况下约束会发生变化
1 添加或移除约束
2 改变约束的值
3 改变约束的优先级
4 将view从view层次结构中移除

最好在改变状态的同时改变约束,比如在button的action中改变约束。

约束的推迟更新

Instead of immediately updating the affected views’ frames, Auto Layout schedules a layout pass for the near future. This deferred pass updates the layout’s constraints and then calculates the frames for all the views in the view hierarchy.

You can schedule your own deferred layout pass by calling the setNeedsLayout method or the setNeedsUpdateConstraints method.

view的frame的更新并不是立即执行的,他会在将来的某个时刻更新layout,重新计算frame。你能够使用setNeedsLayout或者setNeedsUpdateConstraints去告知系统在未来某个时刻更新layout,并重新计算frame。

layout的传递中包含了两个传递
1 update pass:更新必要的约束
2 layout pass:更新view的frame的位置

Update Pass:
根据view的层次调用updateViewConstraints(包括所有的view以及ViewController)

Layout pass:
根据视图层次调用VC的viewWillLayoutSubviews和view的layoutSubViews。默认条件下,layoutSubView更新view的frame。你可以重写这个函数来实现一些自定义行为。

批处理更新

当有大量的约束需要更新时,利用setNeedsUpdateConstraints,然后重写updateViewConstraints
Note:不要在updateViewConstraints中取消约束然后重新定义约束,最好是更新约束的值。

注意:在updateViewConstraints中调用setNeedsUpdateConstraints会造成循环调用

至于重写viewWillLayoutSubviews或者layoutSubView,注意点比较多。注意要素链接

主动更新约束

因为setNeedsUpdateConstraints函数调用后,约束并不是立即更新的所以开发者可以调用updateConstraintsIfNeed函数来主动更新约束,但在某个view中调用这个方法后只会对这个view以及其subView中调用过setNeedsUpdateConstraints函数的view起作用。不要直接去调用UpdateConstraints

视图的固有内容尺寸

视图的固有内容尺寸是指,内容的尺寸会根据视图的尺寸以及约束做出调整


上图中compression约束的优先级(750)高于hugging约束的优先级(250)。所以一般情况下拉伸内容的尺寸比压缩内容的尺寸更加的方便。当多个view需要伸缩或缩小时不知道哪个view的尺寸需要优先更新时可以改变他们compressing和hugging的优先级,从而决定哪个view优先扩张。资料

布局的更新

不要直接调用layoutSubview函数,道理同约束一样。和约束一样调用layoutIfNeeded时候,只对调用该方法的view和其subview中调用过setNeedsLayout函数的view起作用