NSTextView 在黑暗模式下在几乎黑色的地方绘制黑色

NSTextView draws black on almost-black in Dark Mode

当我在深色模式下构建我的 macOS 应用程序时,我的一些文本视图 (NSTextView) 在近乎黑色的背景上呈现黑色文本。在 Interface Builder 的属性检查器中,"Text Color" 设置为系统 "Default (Text Color)",我认为这是正确的。实际上,在 Interface Builder 中,此文本会根据需要在深色模式下呈现白色,在浅色模式下呈现黑色。我已经在我的代码中搜索了我可能以编程方式将此视图中的文本颜色设置为黑色的任何行,但找不到任何行。为什么我的文字总是黑色的?

我注意到错误的文本视图将它们的 "attributed string" 绑定到 Cocoa 绑定到 return 普通的方法,而不是归因于 NSString 对象。我这样做可能是因为几年前我写这个应用程序时很懒惰,但它运行良好。这种不匹配原来是问题所在。解决方法是将这些方法修改为 return 一个 NSAttributedString,其中的属性字典包含 key/value 对

NSForegroundColorAttributeName : NSColor.controlTextColor

可能发生的事情是 Cocoa 旨在 在属性字符串绑定获得非属性字符串时执行您可能想要的操作。 Cocoa 没有拒绝异常,而是应用了一些 "default" 属性,其中包括自 1984 年以来一直是 macOS 默认颜色的黑色文本颜色——在黑暗模式出现之前完全明智!好吧,Apple 将此默认值从黑色更改为 controlTextColor 可能是件好事,但显然他们没有这样做。

结论:我们无法再将文本视图的属性字符串绑定到普通的非属性字符串。

或者,您可以使用@Ely 的答案并绑定到value。但是,如果您尝试这样做,并且在绑定检查器中没有看到 value 绑定,但确实看到了 data 绑定,这是因为 NSTextField 文档中的这些评论:

[value] 绑定仅在 NSTextView 配置为使用单一字体显示时可用。

以后

[data] 绑定仅在 NSTextView 配置为允许多种字体时可用。

他们所说的配置为允许多种字体的意思是,在属性检查器中,允许富文本复选框是在。相反,配置为使用单一字体显示意味着允许富文本复选框关闭。

如果您在 NSTextView 中使用纯文本(例如,因为您需要滚动视图),只需绑定到 value 属性 而不是 attributedString。此绑定将使用控件的文本颜色设置,并与深色模式完美配合。

"plain"(非属性)字符串的 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)
    }
}

使用此代码(macOS Catalina 版本 10.15.3)后对我有用:

if #available(OSX 10.14, *) {         
    textView.usesAdaptiveColorMappingForDarkAppearance = true
} else {
    // Fallback on earlier versions - do nothing
}

我发现这个记录在方法中:

/*************************** 黑暗模式 *************** ************

当是时,启用自适应颜色映射模式。在此模式下,在深色有效外观下,NSTextView 将所有颜色映射为 NSColorTypeComponentBased 通过反转亮度 进出模型对象 NSTextStorage。例如, 渲染时,与 NSColorPanel 和 NSFontManager 交互,以及 转换 from/to 粘贴板和外部格式,颜色 值在模型和渲染上下文之间转换。笔记 颜色转换算法压缩了亮度范围 因此,不保留之间的往返保真度 光明和黑暗的外表。可能不适合富文本 创作,所以提供命令或偏好是个好主意 您的用户可以在没有此选项的情况下或在光线下查看和编辑他们的文档 模式。 */