Swift - 约束优先级问题

时间:2021-03-29 16:51:43

标签: ios swift constraints

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

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

    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.'

我做错了什么?

2 个答案:

答案 0 :(得分:2)

您收到错误,因为您正在删除按钮 2:

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 下可见。

如果您愿意接受其他解决方案,正如此处的其他答案所暗示的那样,您可以使用 UIStackView 为您完成所有工作。只需将两个按钮作为子视图添加到 UIStackView 中,如下所示:

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

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

button2.isHidden = true

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

<块引用>

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

答案 1 :(得分:1)

您可以使用堆栈视图并在其中添加两个按钮,而不是添加约束和删除按钮,然后根据需要显示和隐藏它们。 Stackview 有很多好处,所以它会自己处理其余的事情。