哪个布局约束具有同等优先级?
Posted
技术标签:
【中文标题】哪个布局约束具有同等优先级?【英文标题】:Which layout constraint precedes with equal priority? 【发布时间】:2018-03-02 15:58:55 【问题描述】:给定两个约束:
NSLayoutConstraint.activate([
aView.topAnchor.constraint(equalTo: cView.topAnchor) //#1
aView.topAnchor.constraint(greaterThanOrEqualTo: bView.bottomAnchor, constant: 10) //#2
])
假设约束 #1 中的 cView.topAnchor
小于约束 #2 中的 bView.bottomAnchor
(即“更靠北”)。
这不应该导致自动布局的冲突,因为它不能满足这两个约束,因为它们具有相同的优先级?
奇怪的是它没有 - 至少不在日志窗口中,也不在 Xcode 的调试视图层次结构中。
我的方法是将约束 #1 的优先级设置为 .defaultHigh
,以便自动布局可以打破约束而不会发生冲突。
那么是否有必要设置优先级,因为似乎没有冲突?
【问题讨论】:
【参考方案1】:基于文档的解释
不能同时满足的具有相同优先级的两个(或更多)约束总是会导致冲突。根据documentation:
当系统在运行时检测到无法满足的布局时,会执行以下步骤:
Auto Layout 识别出一组冲突的约束。
它打破了其中一个冲突的约束并检查布局。系统会继续打破约束,直到找到有效的布局。
自动布局将有关冲突和损坏的约束的信息记录到控制台。
文档没有指定哪个约束被破坏 - 它是故意的,因此您不会依赖它,而是通过降低其优先级来明确决定应该破坏哪个约束。
实证评估
您可以通过设置两个绝对冲突的约束来简单地测试行为:
NSLayoutConstraint.activate([
view.heightAnchor.constraint(equalToConstant: 81),
view.heightAnchor.constraint(equalToConstant: 60),
])
这会造成冲突,会在控制台报出:
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:0x1c0099550 molly.QuestionInboxLinkPreView:0x10791dd40.height == 81 (active)>",
"<NSLayoutConstraint:0x1c008c300 molly.QuestionInboxLinkPreView:0x10791dd40.height == 60 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x1c0099550 molly.QuestionInboxLinkPreView:0x10791dd40.height == 81 (active)>
奇怪的是,如果您指定了两个冲突的约束,其中两个约束的优先级都低于所需的优先级('priority
let constraint1 = view.heightAnchor.constraint(equalToConstant: 81)
constraint1.priority = UILayoutPriority(rawValue: 999)
let constraint2 = view.heightAnchor.constraint(equalToConstant: 60)
constraint2.priority = UILayoutPriority(rawValue: 999)
NSLayoutConstraint.activate([constraint1, constraint2])
我猜原因是因为被破坏的约束不是required
,所以系统不太关心报告它。但它可能会导致一些丑陋的情况 - 请注意并小心。
你的榜样
现在考虑你的例子:
NSLayoutConstraint.activate([
aView.topAnchor.constraint(equalTo: cView.topAnchor) //#1
aView.topAnchor.constraint(greaterThanOrEqualTo: bView.bottomAnchor, constant: 10) //#2
])
这两个约束不必相互冲突。您是说a.top = c.top
和a.top >= b.bottom', which can be satisfied if
c.top >= b.bottom. So unless there are other constraints with the same priority that conflict with
c.top >= b.bottom`,自动布局没有理由识别冲突。
另外,如果约束条件不是.required
,即使有也不会报冲突。
【讨论】:
但它是c.top < b.bottom
(我的意思是“约束#1 中的cView.topAnchor 小于约束#2 中的bView.bottomAnchor”)。所以你说一定有冲突,但由于某种原因它没有显示出来,巧合的是,冲突是通过自动布局以我想要的方式解决的?可能是因为在我的代码中 b.bottom
实际上是 view.safeAreaGuide.bottomAnchor
所以它创建了一个没有日志的复杂性。
@Manuel 我必须假设没有真正的冲突并且您误解了您的约束(当约束很复杂时很容易发生这种情况),或者它们的优先级已经不是.required
和在这种情况下,无论如何都不会报告(阅读更新的答案)
约束不太可能被误解,因为我可以通过视觉表示来确认布局。也许自动布局以特殊方式处理涉及safeAreaLayoutGuide
的约束。约束的默认优先级是多少?以上是关于哪个布局约束具有同等优先级?的主要内容,如果未能解决你的问题,请参考以下文章