利用约束优先级解决 AutoLayout 冲突

最近使用 AutoLayout 遇到了个问题。具体的来说,有个使用 Xib 创建的 TableViewCell,其中用 AutoLayout 布局的。布局如下

Cell手稿
由于业务需要,有时候需要动态加载 Cell,考虑一些方案后采取把 Cell 高度设置为 0.01 的方法。但这样会导致一堆错误信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2015-12-30 19:29:16.526 autolayout[28645:2090707] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7a6667a0 V:[UIView:0x7a666580]-(10)-| (Names: '|':UITableViewCellContentView:0x7a666480 )>",
"<NSLayoutConstraint:0x7a666800 V:|-(10)-[UIView:0x7a666580] (Names: '|':UITableViewCellContentView:0x7a666480 )>",
"<NSLayoutConstraint:0x7a65fff0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7a666480(0.49)]>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7a6667a0 V:[UIView:0x7a666580]-(10)-| (Names: '|':UITableViewCellContentView:0x7a666480 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

这个错误在 iOS7 上可能引起崩溃。仔细查看 Log 主要是是因为把内部 View 上下设置为相对于 Cell 相差 10。但是如果 Cell 高度为 0.01,则因为 View 高度不能为负的,所以会不能安全满足约束条件。

这种情况下,可以通过修改约束的优先级(Priority)来解决问题。默认情况下约束优先级为 1000。此时我们修改底部约束优先级为 900 即可解决问题。
修改约束优先级
当出现约束冲突时,主动放弃低优先级的约束。

使用 Snapkit 等 AutoLayout 扩展时也能相应的修改约束优先级来解决问题,如

1
2
3
4
box.snp_makeConstraints { (make) -> Void in
make.height.equalTo(50).priority(900) //方便动态修改高度,避免冲突
make.center.equalTo(self.view)
}