当我在深色模式下构建我的 macOS 应用程序时,我的一些文本视图 (NSTextView) 在几乎黑色的背景上呈现黑色文本。在 Interface Builder 的 Attributes Inspector 中,“文本颜色”设置为系统“默认(文本颜色)”,我认为这是正确的。实际上,在 Interface Builder 中,此文本根据需要在深色模式下呈现白色,在浅色模式下呈现黑色。我已经在我的代码中搜索了我可能会以编程方式将此视图中的文本颜色设置为黑色的任何行,但找不到任何行。为什么我的文字总是黑色的?
4 回答
我注意到错误的文本视图使用 Cocoa 绑定将它们的“属性字符串”绑定到返回普通的方法,而不是属性 NSString 对象。我这样做可能是因为几年前我写这个应用程序时很懒,而且效果很好。事实证明,这种不匹配是问题所在。修复方法是修改这些方法以返回一个 NSAttributedString,其中包含一个包含键/值对的属性字典
NSForegroundColorAttributeName : NSColor.controlTextColor
可能发生的事情是 Cocoa 被设计为在属性字符串绑定获取非属性字符串时执行您可能想要的操作。Cocoa 并没有抛出异常,而是应用了一些“默认”属性,其中包括自 1984 年以来一直是 macOS 默认的黑色文本颜色——在黑暗模式出现之前完全合理!好吧,Apple 可能会很好地将这个默认值从黑色更改为 controlTextColor,但显然他们没有。
结论:我们不能再将文本视图的属性字符串绑定到普通的非属性字符串。
或者,您可以使用@Ely 的答案并绑定到value
. 但是,如果您尝试这样做value
,但在 Bindings Inspector 中没有看到绑定,但确实看到了data
绑定,那是因为 NSTextField 文档中的这些注释:
[ value
] 绑定仅在 NSTextView 配置为使用单一字体显示时可用。
然后
[ data
] 绑定仅在 NSTextView 配置为允许多种字体时可用。
配置为允许多种字体的意思是,在属性检查器中,允许富文本复选框已打开。相反, 配置为使用单一字体显示意味着“允许富文本”复选框处于关闭状态。
使用此代码后它对我有用(macOS Catalina 版本 10.15.3):
if #available(OSX 10.14, *) {
textView.usesAdaptiveColorMappingForDarkAppearance = true
} else {
// Fallback on earlier versions - do nothing
}
我在方法中发现了这一点:
/****************************** 黑暗模式 ******************** *******
为 YES 时,启用自适应颜色映射模式。在这种暗色有效外观下的模式下,NSTextView 通过在进出模型对象 NSTextStorage 时反转亮度来将所有颜色映射到 NSColorTypeComponentBased。例如,在渲染、与 NSColorPanel 和 NSFontManager 交互以及从/转换粘贴板和外部格式时,颜色值在模型和渲染上下文之间转换。请注意,颜色转换算法会压缩亮度范围,因此不会保留明暗外观之间的往返保真度。它可能不适合富文本创作,因此最好为您的用户提供一个命令或首选项,以便在不使用此选项或在轻量模式下查看和编辑他们的文档。*/
如果您在 NSTextView 中使用纯文本(例如,因为您需要滚动视图),只需绑定到value
属性而不是attributedString
. 此绑定将使用控件的文本颜色设置,并与深色模式完美配合。
“普通”(非属性)字符串的 NSTextView 扩展。在明暗模式下工作:
extension NSTextView {
static let DefaultAttribute =
[NSAttributedString.Key.foregroundColor: NSColor.textColor] as [NSAttributedString.Key: Any]
var stringValue: String {
return textStorage?.string ?? ""
}
func setString(_ string: String) {
textStorage?.mutableString.setString("")
append(string)
}
func append(_ string: String) {
let attributedText = NSAttributedString(string: string, attributes: NSTextView.DefaultAttribute)
textStorage?.append(attributedText)
}
}