正在更新为暗模式:NSColor是否忽略外观更改?

时间:2018-09-25 18:44:56

标签: cocoa nscolor macos-mojave

在我的Web视图中,我使用CSS变量在运行时更改各种颜色,具体取决于是否启用了macOS 10.14的暗模式。一切正常。棘手的部分是在系统外观更改时更新颜色。

我正在通过观察窗口上的effectiveAppearance属性来检测更改。该通知会按预期方式通过,但是当我去更新颜色时,NSColor仍然为我提供了深色模式的颜色(或应用程序以哪种模式启动)。例如,当我响应从暗模式到亮模式的切换时,NSColor.textColor仍然是白色而不是黑色。我自己的色彩资产似乎也发生了同样的情况。

我是否应该以其他方式或时间获得这些颜色?还是这可能是操作系统错误?

编辑: 我还尝试创建WebView的子类,并在Web视图的有效外观名称更改的情况下更新drawRect()中的颜色。第一次,即使应用在黑暗模式下启动,我也会获得所有浅色。之后,当我从浅色模式切换为深色时,会得到深色的系统颜色和浅色的资产目录颜色。

在调试器之外,切换到暗模式是可行的,但是初始负载始终为浅色。

2 个答案:

答案 0 :(得分:10)

更改系统外观不会更改当前外观which you can query and set and is independent from the system appearance。但是外观实际上取决于“拥有”视图,因为在同一视图层次结构中,由于充满活力并在视图上手动设置appearance属性,因此可能会出现几种外观。

在某些情况下,例如在drawRect:updateLayerlayoutupdateConstraints中,可可已经updates the current appearance。在其他任何地方,您都应该这样:

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

答案 1 :(得分:1)

以及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出现的。