如何在 UITableView 或 UICollectionView 中使用变量 UIStackView?

How to use a variable UIStackView in UITableView or UICollectionView?

我目前正在使用 UICollectionView 构建通用表单生成器。

每个表单元素都是一个单元格,对于复选框,我在单元格内使用 UIStackView 来显示所有可用选项。

问题是每次我重复使用该单元格时,即使我删除了所有 arrangedSubviews,它们仍留在新视图中。

以下代码是我所做的简化版本:

class cell: UICollectionViewCell {

    @IBOutlet weak var stackView: UIStackView!

    func setup(options: [String]) {

        for option in options {
            let label = UILabel()
            label.text = option
            stackView.addArrangedSubview(label)
        }

    }

    override func prepareForReuse() {
        super.prepareForReuse()
        optionsStackView.arrangedSubviews.forEach({ optionsStackView.removeArrangedSubview(view: [=10=]) })
    }

}

相反,我目前的解决方法是隐藏() prepareForReuse() 中的每个 arrangedSubview 而不是删除它们,但我不喜欢那样。

如果您阅读 Xcode 文档中关于 removeArrangedSubview 方法的内容,他们会说:

Discussion: This method removes the provided view from the stack’s arrangedSubviews array. The view’s position and size will no longer be managed by the stack view. However, this method does not remove the provided view from the stack’s subviews array; therefore, the view is still displayed as part of the view hierarchy.

To prevent the view from appearing on screen after calling the stack’s removeArrangedSubview: method, explicitly remove the view from the subviews array by calling the view’s removeFromSuperview() method, or set the view’s isHidden property to true.

因此您还需要从堆栈视图中删除子视图。 (当我第一次开始使用堆栈视图时,我也为此苦苦挣扎。)

编辑:

事实上,正如@kid_x 指出的那样,只需删除带有 removeFromSuperView() 的子视图即可。我不确定 removeArrangedSubview() 的意义是什么,TBH。


编辑#2:

我建议完全不要使用 removeArrangedSubview()。相反,请执行以下操作之一:

选项 1: 如果您需要从堆栈视图中永久删除视图,只需使用 removeFromSuperView().

选项 2: 如果您想从堆栈视图中删除视图,然后再将它们放回去,只需切换子视图的 isHidden 属性,如 suprandr 的回答中所述。堆栈视图将关闭空的 space 并重新定位剩余的视图,就像您删除它们一样。

在许多情况下,由于从可重用视图中的父视图中删除可能(而且大多数情况下会)导致视图被释放,所以在 UIStackView 中只需放置

dynamicView.isHidden = false

删除并

dynamicView.isHidden = true

再次添加,会导致stack view重新排列其他排列的view。