首页 > 解决方案 > Swift - 约束优先级问题

问题描述

我目前有一个带有两个大按钮的布局,一个在另一个上面,在它们下面有一些图标按钮。

第二个大按钮可以出现也可以不出现。我想要的是图标按钮的顶部约束是可见的大按钮的底部约束。我正在使用优先级为图标按钮设置两个约束:

    let topToBut2 = iconButton.topAnchor.constraint(equalTo: button2.bottomAnchor)
    topToBut2.isActive = true
    
    let topToBut1 = iconButton.topAnchor.constraint(equalTo: button1.bottomAnchor)
    topToBut1.priority = UILayoutPriority(500)
    topToBut1.isActive = true

在 viewDidLoad 上,根据可用的数据,我会

    button2.removeFromSuperview()

但是,一旦我删除 button2 我得到

'Unable to activate constraint with anchors <...> and <...> because they have no common ancestor.  Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.'

我究竟做错了什么?

标签: iosswiftconstraints

解决方案


您收到错误消息,因为您正在删除 button2:

button2.removeFromSuperview()

此后,您尝试激活对其的约束:

let topToBut1 = iconButton.topAnchor.constraint(equalTo: button1.bottomAnchor)
topToBut1.priority = UILayoutPriority(500)
topToBut1.isActive = true

因此,在这里您删除第二个按钮以使第一个按钮顶部约束处于活动状态的方法并不是很好。您可以改为检查第二个按钮是否应该可见并相应地设置 iconButton 约束,而不使用优先级或两个不同的约束:

if secondButtonVisible {
    iconButton.topAnchor.constraint(equalTo: button2.bottomAnchor).isActive = true
} else {
    iconButton.topAnchor.constraint(equalTo: button1.bottomAnchor).isActive = true
}

但是你也不应该忘记将第二个按钮hidden属性设置为 false(而不仅仅是从超级视图中删除它),否则它将在 iconButton 下可见。

如果您对其他解决方案持开放态度,正如此处其他答案所建议的那样,您可以使用 aUIStackView为您完成所有工作。只需将两个按钮作为子视图添加到UIStackView如下:

stackView.addArrangedSubview(button1)
stackView.addArrangedSubview(button2)

当你想隐藏你的第二个按钮时,你只需改变它的隐藏属性:

button2.isHidden = true

这将隐藏第二个按钮并相应地更新布局。根据文档:

每当视图被添加、删除或插入到排列的子视图数组中,或者每当排列的子视图的 isHidden 属性之一发生变化时,堆栈视图都会自动更新其布局。


推荐阅读