哪个布局约束具有同等优先级?

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.topa.top &gt;= 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 &lt; b.bottom(我的意思是“约束#1 中的cView.topAnchor 小于约束#2 中的bView.bottomAnchor”)。所以你说一定有冲突,但由于某种原因它没有显示出来,巧合的是,冲突是通过自动布局以我想要的方式解决的?可能是因为在我的代码中 b.bottom 实际上是 view.safeAreaGuide.bottomAnchor 所以它创建了一个没有日志的复杂性。 @Manuel 我必须假设没有真正的冲突并且您误解了您的约束(当约束很复杂时很容易发生这种情况),或者它们的优先级已经不是.required 和在这种情况下,无论如何都不会报告(阅读更新的答案) 约束不太可能被误解,因为我可以通过视觉表示来确认布局。也许自动布局以特殊方式处理涉及safeAreaLayoutGuide 的约束。约束的默认优先级是多少?

以上是关于哪个布局约束具有同等优先级?的主要内容,如果未能解决你的问题,请参考以下文章

自动布局约束优先级未解决

如何使用自动布局约束为移动 UILabel 设置动画?

使用自动布局约束优先级来改变不同设备上的视图大小

等宽和设置优先级的自动布局

什么是_UITemporaryLayoutWidth,为什么它会破坏我的约束?

Masonry设置约束优先级[转]