5

大多数与此相关的问题和答案都基于旧版本的 Xcode 和 Swift。此外,90% 的问题与 UIKit 和绘制自定义控件有关。

我正在添加一个标准按钮,它位于自定义控件的中心,用IBDesignable.

import Cocoa

@IBDesignable public class ButtonPresetView: NSView {
    public override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        initialControlSetup()
    }

    public required init?(coder decoder: NSCoder) {
        super.init(coder: decoder)
        initialControlSetup()
    }

    private func initialControlSetup() {
        let button = NSButton(title: "Hello", target: nil, action: nil)
        button.translatesAutoresizingMaskIntoConstraints = false
        addSubview(button)

        // Configure button
        centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
        centerYAnchor.constraint(equalTo: button.centerYAnchor).isActive = true
    }
}

我向应用程序添加了一个自定义视图,并将 Identity Inspector 中的类属性设置为我的自定义类 ( ButtonPresetView)。

它应该显示以画布为中心的按钮,但画布是空白的。不确定有多少人以这种方式使用它,但它在 Xcode 8.3 中与 Swift 3 完美配合。

还有其他人有这个问题吗?

4

2 回答 2

2

通过将以下两行添加到函数的顶部,我能够使其在最新的 Xcode 中initialControlSetup工作:

wantsLayer = true
canDrawSubviewsIntoLayer = true

我认为这基本上告诉了NSView以更类似于 iOS 工作方式的方式进行渲染。如果这在您所说的 Xcode 8.3 中有效,那么 Apple 可能在 Xcode 9 中引入了这种回归而没有意识到这一点。

于 2017-12-08T08:04:53.087 回答
0

戴夫的回答是正确的,我只想记下这个解决方案的后果。

canDrawSubviewsIntoLayer设置为 时true,其所有未专门启用的子视图将使用设置为wantsLayer的父视图的图层呈现其内容。canDrawSubviewsIntoLayertrue

这意味着子视图动画被禁用,因为它们缺少自己的支持层。为了防止在运行时发生这种情况,您可以放入canDrawSubviewsIntoLayer = true函数prepareForInterfaceBuilder()中。

奇怪的是,如果您明确设置,Interface Builder 不会呈现控件,button.wantsLayer = true根据“canDrawSubviewsIntoLayer”文档,它应该为控件提供自己的支持层,而不是将自身呈现到父层中。这纯粹是猜测,但我猜测是一种优化,Interface Builder 仅呈现内容视图的顶层/控件。

于 2017-12-10T22:16:35.123 回答