Xcode 9.2 和 Swift 4 中的 AppKit 是否损坏了 IBDesignable?
Is IBDesignable broken for AppKit in Xcode 9.2 and Swift 4?
与此相关的大多数问题和答案都基于 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
}
}
我向应用程序添加了一个自定义视图,并将身份检查器中的 class 属性 设置为我的自定义 class (ButtonPresetView
).
它应该显示位于 canvas 中心的按钮,但 canvas 是空白的。
不确定有多少人以这种方式使用它,但它在 Xcode 8.3.
中与 Swift 3 一起工作得很好
还有其他人遇到这个问题吗?
通过将以下两行添加到 initialControlSetup
函数的顶部,我能够在最新的 Xcode 中使用它:
wantsLayer = true
canDrawSubviewsIntoLayer = true
我认为这基本上告诉 NSView
以更类似于 iOS 的工作方式的方式呈现。如果如您所说这在 Xcode 8.3 中有效,则 Apple 可能在 Xcode 9 中引入了此回归而没有意识到。
Dave 的回答是正确的,我只是想记下这个解决方案的后果。
当 canDrawSubviewsIntoLayer
设置为 true
时,其所有未具体启用 wantsLayer
的子视图将使用带有 canDrawSubviewsIntoLayer
设置为 true
.
这意味着子视图动画被禁用,因为它们缺少自己的支持层。为了防止在运行时发生这种情况,您可以将 canDrawSubviewsIntoLayer = true
放入 prepareForInterfaceBuilder()
函数中。
奇怪的是,Interface Builder 不会渲染控件,如果您明确设置 button.wantsLayer = true
,根据 "canDrawSubviewsIntoLayer" 文档,它应该为控件提供自己的支持层而不是渲染本身进入父层。
这纯粹是猜测,但我猜测是一种优化,Interface Builder 仅呈现内容视图的顶部 layers/controls。
与此相关的大多数问题和答案都基于 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
}
}
我向应用程序添加了一个自定义视图,并将身份检查器中的 class 属性 设置为我的自定义 class (ButtonPresetView
).
它应该显示位于 canvas 中心的按钮,但 canvas 是空白的。 不确定有多少人以这种方式使用它,但它在 Xcode 8.3.
中与 Swift 3 一起工作得很好还有其他人遇到这个问题吗?
通过将以下两行添加到 initialControlSetup
函数的顶部,我能够在最新的 Xcode 中使用它:
wantsLayer = true
canDrawSubviewsIntoLayer = true
我认为这基本上告诉 NSView
以更类似于 iOS 的工作方式的方式呈现。如果如您所说这在 Xcode 8.3 中有效,则 Apple 可能在 Xcode 9 中引入了此回归而没有意识到。
Dave 的回答是正确的,我只是想记下这个解决方案的后果。
当 canDrawSubviewsIntoLayer
设置为 true
时,其所有未具体启用 wantsLayer
的子视图将使用带有 canDrawSubviewsIntoLayer
设置为 true
.
这意味着子视图动画被禁用,因为它们缺少自己的支持层。为了防止在运行时发生这种情况,您可以将 canDrawSubviewsIntoLayer = true
放入 prepareForInterfaceBuilder()
函数中。
奇怪的是,Interface Builder 不会渲染控件,如果您明确设置 button.wantsLayer = true
,根据 "canDrawSubviewsIntoLayer" 文档,它应该为控件提供自己的支持层而不是渲染本身进入父层。
这纯粹是猜测,但我猜测是一种优化,Interface Builder 仅呈现内容视图的顶部 layers/controls。