我想出了一个不同的解决方案。如果 Cocoa 支持 @IBOutletCollection,子类化 NSTableCellView 会很好。因为那时我可以有一个 Cell 子类,其中包含单元格中所有 NSTextFields 的数组。但由于我有多种类型的单元格和不同数量的 NSTextField,我不喜欢这个选项。相反,我查看了 Apple 为backgroundStyle
NSTableCellView 中的属性提供的文档。
默认实现会自动将调用转发到所有实现 setBackgroundStyle: 或者是 NSControl 的子视图,这些子视图具有响应 backgroundStyle 的 NSCell 类。
如果我的 TextFields 实现了 setBackgroundStyle,那么它们应该在单元格选择发生变化时得到通知。但是,背景样式的这种转发不是递归的。因为我的 NSTextFields 在 NSStackViews 中,所以他们没有收到消息。为了解决这个问题,我刚刚编写了一个扩展来在所有 NSView 上实现 setBackgroundStyle。它只是转发消息。最后,我为 NSTextField 添加了一个扩展来实现这个方法。从这个扩展中,我改变了文本颜色并调用了 super。这个解决方案也很好,因为不需要子类。没有 NSTableCellView 或 NSTextField 的子类。
将此功能添加到所有视图和所有 NSTextFields 可能会导致不在 NSTableViews 中的 NSTextFields 出现意外更改颜色的问题。但到目前为止,只有我的 TableViews/OutlineViews 中的那些正在改变颜色,而这正是我正在寻找的。如果您看到文本字段更改了您不期望的颜色,您可能希望继承 NSTextField 并仅在该子类上实现 setBackgroundStyle 覆盖,而不是将其添加到所有 NSTextFields。
我使用的 Swift 3 中的代码粘贴在下面。
extension NSView {
func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
for view in self.subviews {
view.setBackgroundStyle(newValue)
}
}
}
extension NSTextField {
override func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
switch newValue {
case .dark:
self.textColor = NSColor.controlLightHighlightColor
case .light, .lowered, .raised:
self.textColor = NSColor.labelColor
}
super.setBackgroundStyle(newValue)
}
}