以编程方式将 InterfaceBuilder 创建的视图添加到 NSStackView 会将它们压缩到 0 高度

Programmatically adding InterfaceBuilder-created views to an NSStackView squashes them to 0 height

我一直在尝试将我在 Interface Builder 中创建的自定义视图添加到 NSStackView,但失败得很惨。

这是我的视图控制器。它目前除了从 NIB 初始化视图外什么都不做:

class ServiceControlViewController : NSViewController {
    init() {
        super.init(nibName: "ServiceControlView", bundle: nil)!
    }
}

下面是我尝试将新创建的视图添加到堆栈视图的方式(这发生在应用程序委托中):

@IBOutlet weak var stackView: NSStackView!

@IBAction func addButtonClicked(sender: AnyObject) {
    let viewController = ServiceControlViewController()
    stackView.addView(viewController.view, in: .top)
    stackView.layoutSubtreeIfNeeded()
}

当我在将创建的视图添加到堆栈视图之前打印它的框架时,它具有正确的大小。如果我之后打印它,它会被压扁到零高度。我怀疑发生了一些我不明白的自动调整大小的魔法,但我无法修复它。

有趣的是,如果我将 ServiceControlViewController 的视图设置为例如是 NSButton,那么它会被正确添加并且不会被压缩到零高度。它只发生在我创建的 Custom Views 中。

PS:我的 InterfaceBuilder 创建的视图只包含一堆按钮和一个标签:

PPS: 我添加了 an MWE

似乎对该自定义视图没有限制,使其大于零大小。 您必须确定其大小调整行为是什么,例如它总是相同的大小,还是可以调整最小值等。

然后在 IB 中,您可以构建创建该效果所需的约束。例如。:

或者,您可以将这些控件放入堆栈视图中以获得类似的结果。

Interestingly enough, if I set the ServiceControlViewController's view to e.g. be an NSButton, then it is correctly added and not squashed to zero height. It only happens with the Custom Views I create.

正确。这是因为 NSButton 具有您的自定义 NSView 所没有的东西:intrinsicContentSize。这是堆栈视图用来调整和定位您添加的视图的内容。

因此,在您的自定义视图中覆盖 intrinsicContentSize,一切都会好起来的。