Xcode 9.2 和 Swift 4 中的 AppKit 的 IBDesignable 是不是损坏?
Posted
技术标签:
【中文标题】Xcode 9.2 和 Swift 4 中的 AppKit 的 IBDesignable 是不是损坏?【英文标题】:Is IBDesignable broken for AppKit in Xcode 9.2 and Swift 4?Xcode 9.2 和 Swift 4 中的 AppKit 的 IBDesignable 是否损坏? 【发布时间】:2017-12-05 20:28:48 【问题描述】:与此相关的大多数问题和答案都基于旧版本的 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 完美配合。
还有其他人有这个问题吗?
【问题讨论】:
【参考方案1】:通过将以下两行添加到 initialControlSetup
函数的顶部,我能够使其在最新的 Xcode 中工作:
wantsLayer = true
canDrawSubviewsIntoLayer = true
我认为这基本上告诉NSView
以更类似于 ios 工作方式的方式呈现。如果如您所说,这在 Xcode 8.3 中有效,那么 Apple 可能在 Xcode 9 中引入了这种回归,而没有意识到这一点。
【讨论】:
分层是默认开启的,所以wantsLayer = true
是不必要的。
我不知道 AppKit 在这方面做出了任何改变。您是否有确认默认值已更改的链接?或者你是说仅仅将canDrawSubviewIntoLayer
设置为true
会打开NSView
自己的层?
对不起,我的措辞是错误的。默认情况下,自定义控件中不启用图层支持。我的意思是说,在一个新的 AppKit 项目中,内容视图默认是层支持的,因此它的所有子视图也是如此。
其实我相信你是对的。 canDrawSubviewIntoLayer
似乎是 Apple 的一项举措,以使 AppKit 渲染模型与 UIKit 渲染模型保持一致。我发现,如果您取消选中 layer-backed content view,canDrawSubviewIntoLayer
也是不必要的,它的工作方式与 xCode 8.3 中的一样。谢谢您的帮助。这让我发疯了。【参考方案2】:
Dave 的回答是正确的,我只是想记录一下这个解决方案的后果。
当canDrawSubviewsIntoLayer
设置为true
时,其所有未专门启用wantsLayer
的子视图将使用将canDrawSubviewsIntoLayer
设置为true
的父视图层呈现其内容。
这意味着子视图动画被禁用,因为它们缺少自己的支持层。为了防止在运行时发生这种情况,您可以将canDrawSubviewsIntoLayer = true
放入prepareForInterfaceBuilder()
函数中。
奇怪的是,如果您明确设置button.wantsLayer = true
,Interface Builder 不会呈现控件,根据“canDrawSubviewsIntoLayer”文档,它应该为控件提供自己的支持层,而不是将自身呈现到父层中。
这纯粹是猜测,但我猜测是一种优化,Interface Builder 仅呈现内容视图的顶层/控件。
【讨论】:
以上是关于Xcode 9.2 和 Swift 4 中的 AppKit 的 IBDesignable 是不是损坏?的主要内容,如果未能解决你的问题,请参考以下文章
为啥应用存档在 iOS、swift、xcode 9.2 中使用自定义框架失败
Xcode 9 Swift 4 Playgrounds UIGestureRecognizer 不工作