更新暗模式:NSColor 忽略外观变化?
Updating for dark mode: NSColor ignores appearance changes?
在我的网络视图中,我使用 CSS 变量在运行时更改各种颜色,具体取决于是否启用了 macOS 10.14 的深色模式。这么多工作正常。棘手的部分是在系统外观发生变化时更新颜色。
我正在通过观察 window 上的 effectiveAppearance
属性 来检测变化。该通知按预期通过,但当我去更新颜色时,NSColor
仍然给我黑暗模式颜色(或应用程序启动的任何模式)。例如,当我响应从暗模式切换到亮模式时,NSColor.textColor
仍然是白色而不是黑色。我自己的颜色资产似乎也发生了同样的情况。
我应该通过其他方式或时间获得这些颜色吗?或者这可能是一个 OS 错误?
编辑:
我还尝试创建 WebView
的子类,并在 Web 视图的有效外观名称发生变化时更新 drawRect()
中的颜色。第一次,我得到了所有浅色,即使应用程序以深色模式启动也是如此。之后,当我从浅色模式切换到深色模式时,我得到系统颜色的深色版本和资产目录颜色的浅色版本。
在调试器之外,切换到深色模式是可行的,但初始加载总是变成浅色。
更改系统外观不会更改 当前 外观,which you can query and set and is independent from the system appearance。但外观实际上取决于同一视图层次结构中的 "owning" 视图,由于活力以及手动设置视图上的 appearance
属性 可能会出现多个外观。
Cocoa 在某些情况下已经 updates the current appearance,例如 drawRect:
、updateLayer
、layout
和 updateConstraints
。在其他地方,你应该这样做:
NSAppearance * saved = [NSAppearance currentAppearance];
[NSAppearance setCurrentAppearance:someView.effectiveAppearance];
// Do your appearance-dependent work, like querying the CGColor from
// a dynamic NSColor or getting its RGB values.
[NSAppearance setCurrentAppearance:saved];
以及 DarkDust 提出的解决方案的 Swifty 版本:
extension NSAppearance {
static func withAppAppearance<T>(_ closure: () throws -> T) rethrows -> T {
let previousAppearance = NSAppearance.current
NSAppearance.current = NSApp.effectiveAppearance
defer {
NSAppearance.current = previousAppearance
}
return try closure()
}
}
您可以与
一起使用
NSAppearance.withAppAppearance {
let bgColor = NSColor.windowBackgroundColor
// ...
}
请注意,我正在从 NSApp 中获取外观,但它可能来自 NSWindow 或 NSView。
在我的网络视图中,我使用 CSS 变量在运行时更改各种颜色,具体取决于是否启用了 macOS 10.14 的深色模式。这么多工作正常。棘手的部分是在系统外观发生变化时更新颜色。
我正在通过观察 window 上的 effectiveAppearance
属性 来检测变化。该通知按预期通过,但当我去更新颜色时,NSColor
仍然给我黑暗模式颜色(或应用程序启动的任何模式)。例如,当我响应从暗模式切换到亮模式时,NSColor.textColor
仍然是白色而不是黑色。我自己的颜色资产似乎也发生了同样的情况。
我应该通过其他方式或时间获得这些颜色吗?或者这可能是一个 OS 错误?
编辑:
我还尝试创建 WebView
的子类,并在 Web 视图的有效外观名称发生变化时更新 drawRect()
中的颜色。第一次,我得到了所有浅色,即使应用程序以深色模式启动也是如此。之后,当我从浅色模式切换到深色模式时,我得到系统颜色的深色版本和资产目录颜色的浅色版本。
在调试器之外,切换到深色模式是可行的,但初始加载总是变成浅色。
更改系统外观不会更改 当前 外观,which you can query and set and is independent from the system appearance。但外观实际上取决于同一视图层次结构中的 "owning" 视图,由于活力以及手动设置视图上的 appearance
属性 可能会出现多个外观。
Cocoa 在某些情况下已经 updates the current appearance,例如 drawRect:
、updateLayer
、layout
和 updateConstraints
。在其他地方,你应该这样做:
NSAppearance * saved = [NSAppearance currentAppearance];
[NSAppearance setCurrentAppearance:someView.effectiveAppearance];
// Do your appearance-dependent work, like querying the CGColor from
// a dynamic NSColor or getting its RGB values.
[NSAppearance setCurrentAppearance:saved];
以及 DarkDust 提出的解决方案的 Swifty 版本:
extension NSAppearance {
static func withAppAppearance<T>(_ closure: () throws -> T) rethrows -> T {
let previousAppearance = NSAppearance.current
NSAppearance.current = NSApp.effectiveAppearance
defer {
NSAppearance.current = previousAppearance
}
return try closure()
}
}
您可以与
一起使用NSAppearance.withAppAppearance {
let bgColor = NSColor.windowBackgroundColor
// ...
}
请注意,我正在从 NSApp 中获取外观,但它可能来自 NSWindow 或 NSView。