更新深色模式:NSColor 忽略外观变化?

问题描述 投票:0回答:5

在我的 Web 视图中,我使用 CSS 变量在运行时根据是否启用 macOS 10.14 的深色模式来更改各种颜色。就这么多,工作正常。棘手的部分是当系统外观发生变化时更新颜色。

我通过观察窗口上的

effectiveAppearance
属性来检测变化。该通知按预期发送,但是当我去更新颜色时,
NSColor
仍然给我黑暗模式颜色(或应用程序启动的任何模式)。例如,当我响应从暗模式到亮模式的切换时,
NSColor.textColor
仍然是白色而不是黑色。我自己的颜色资产似乎也发生了同样的情况。

我应该有不同的方式或时间来获取这些颜色吗?或者这可能是操作系统错误?

编辑: 我还尝试创建

WebView
的子类,并在 Web 视图的有效外观名称发生变化时更新
drawRect()
中的颜色。第一次,我得到了所有浅色,即使应用程序在深色模式下启动也是如此。之后,当我从浅色模式切换到深色模式时,我会得到系统颜色的深色版本和资产目录颜色的浅色版本。

在调试器之外,可以切换到深色模式,但初始加载始终会获得浅色。

cocoa nscolor macos-mojave
5个回答
25
投票

更改系统外观不会更改当前外观,您可以查询和设置并且独立于系统外观。但外观实际上取决于“拥有”视图,因为在同一视图层次结构中,由于活力以及在视图上手动设置

appearance
属性,可能会出现多种外观。

Cocoa 已经在某些情况下更新了当前外观,例如

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];

4
投票

以及 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。


3
投票

正如 @chrstphrchvz 所提到的,使用 macOS 11 或更高版本时,

NSAppearance.current
已被弃用。使用最新外观系统设置更新任何内容的新方法如下:

NSAppearance.currentDrawing().performAsCurrentDrawingAppearance {
    // Update your window or control or whatever
}

2
投票

之前答案中使用的

currentAppearance
属性现已弃用。从 macOS 11 Big Sur 开始,替代方法是使用
performAsCurrentDrawingAppearance:
实例方法。


0
投票
NSApplication.shared.effectiveAppearance.performAsCurrentDrawingAppearance { self.layer?.backgroundColor = colorCustom?.cgColor }
© www.soinside.com 2019 - 2024. All rights reserved.