Swift - 约束优先级问题

Swift - Problem with constraints priority

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

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

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

我做错了什么?

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

您正在删除按钮 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

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

The stack view automatically updates its layout whenever views are added, removed or inserted into the arrangedSubviews array, or whenever one of the arranged subviews’s isHidden property changes.