如何在 macOS 10.14 上检测暗模式?

     2023-05-08     22

关键词:

【中文标题】如何在 macOS 10.14 上检测暗模式?【英文标题】:How can dark mode be detected on macOS 10.14? 【发布时间】:2019-01-11 07:37:20 【问题描述】:

在 macOS 10.14 中,用户可以选择采用系统范围的浅色或深色外观,我需要根据当前模式手动调整一些颜色。

【问题讨论】:

【参考方案1】:

由于您通常通过effectiveAppearance 获得的实际外观对象是复合外观,因此直接询问其名称可能不是可靠的解决方案。

请求currentAppearance 通常也不是一个好主意,因为视图可能被明确设置为浅色模式,或者您想知道在 drawRect: 之外的视图是亮还是暗模式切换后得到不正确的结果。

我想出的解决方案是这样的:

BOOL appearanceIsDark(NSAppearance * appearance)

    if (@available(macOS 10.14, *)) 
        NSAppearanceName basicAppearance = [appearance bestMatchFromAppearancesWithNames:@[
            NSAppearanceNameAqua,
            NSAppearanceNameDarkAqua
        ]];
        return [basicAppearance isEqualToString:NSAppearanceNameDarkAqua];
     else 
        return NO;
    

您可以像appearanceIsDark(someView.effectiveAppearance) 一样使用它,因为如果您明确设置someView.appearance,特定视图的外观可能与另一个视图的外观不同。

您还可以在NSAppearance 上创建一个类别并添加一个- (BOOL)isDark 方法来获取someView.effectiveAppearance.isDark(最好选择一个Apple 将来不太可能使用的名称,例如通过添加供应商前缀)。

【讨论】:

你可以使用NSApp.mainWindow.effectiveAppearance @MuntashirAkon:您不需要将其称为“来自”视图,这无关紧要。您只需要确定上下文的 一个 视图,例如作为备用应用程序的主视图。 您必须从drawRect 调用它吗? viewDidLayout呢? 这段代码曾经为我工作。但在将 Xcode 更新到 11.4 之后,它神秘地不再工作了。在明暗模式下,它都会返回 Aqua 模式。其他人有同样的问题吗? @93sauu 这样做似乎有竞争条件。 NSApp.effectiveAppearance 似乎是检测系统范围设置的更好方法。【参考方案2】:

我已经使用当前外观检查系统是否为 10.14

+ (BOOL)isDarkMode 
    NSAppearance *appearance = NSAppearance.currentAppearance;
    if (@available(*, macOS 10.14)) 
        return appearance.name == NSAppearanceNameDarkAqua;
    

    return NO;

要检测视图中模式的变化,方法是:

- (void)updateLayer;
- (void)drawRect:(NSRect)dirtyRect;
- (void)layout;
- (void)updateConstraints;

要检测视图控制器中模式的变化,方法是:

- (void)updateViewConstraints;
- (void)viewWillLayout;
- (void)viewDidLayout;

使用通知:

// Monitor menu/dock theme changes...
[NSDistributedNotificationCenter.defaultCenter addObserver:self selector:@selector(themeChanged:) name:@"AppleInterfaceThemeChangedNotification" object: nil];

-(void)themeChanged:(NSNotification *) notification 
    NSLog (@"%@", notification);

更多信息Dark Mode Documentation

【讨论】:

对外观变化做出反应的最佳方式是-[NSView viewDidChangeEffectiveAppearance]。您还可以 KVO 视图的 effectiveAppearance 属性,例如,如果您想对视图控制器中的外观更改做出反应。请记住,视图的外观可能与“当前”或系统外观不同。 NSAppearance.currentAppearance 在用户在亮模式和暗模式之间切换时并不总是有效,反之亦然。 NSAppearance.currentAppearance 返回对象在当前线程上处于活动状态的外观,因此您无法确定,因为当前对象可能分配了AquaDark Aqua 来代替Inherited。所以最好的解决方案是使用someView.effectiveAppearance AppleInterfaceThemeChangedNotification 对我不起作用。而是使用viewDidLayout 调用您的暗/亮模式方法。【参考方案3】:

斯威夫特 4

func isDarkMode(view: NSView) -> Bool 
    if #available(OSX 10.14, *) 
        return view.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
    
    return false

【讨论】:

我建议去掉那个可选的:在很多情况下NSAppearance.currentAppearance 可能会给出错误的结果(例如,如果你在方法mentioned in this answer 之外调用它并且用户更改了系统外观,NSAppearance.currentAppearance 可能仍会返回旧系统外观)。因此,请始终询问有关其有效外观的具体观点。 此外,appearance.name == .darkAqua 的检查在某些情况下也可能是错误的,因为 实际 外观是“复合”。这就是为什么 bestMatch(from:) 存在并且应该被使用的原因。 感谢您的建议。答案已更新。【参考方案4】:

实际上有 8 个可能的appearances 用于视图,其中 4 个用于普通用途。也就是说,

    NSAppearanceNameAqua 灯光模式, NSAppearanceNameDarkAqua 黑暗模式, NSAppearanceNameAccessibilityHighContrastAqua 增加对比度的灯光模式(从辅助功能设置), NSAppearanceNameAccessibilityHighContrastDarkAqua 增加对比度的暗模式。

直接比较

appearance.name == NSAppearanceNameDarkAqua;

如果对比度增加,可能无法检测暗模式。因此,请始终使用bestMatchFromAppearancesWithNames

最好考虑到高对比度的外观以获得更好的可访问性。

【讨论】:

【参考方案5】:

对我来说,如果我想要一个全局状态,而不是每个视图,并且我无权访问视图,并且我希望收到更新通知,那么这些答案都不起作用。

解决方案是在主线程中请求NSApp.effectiveAppearance,或者至少当前回调方法返回系统之后。

所以,首先我必须按照 Saúl Moreno Abril 的指示进行注册,代码如下:

[NSDistributedNotificationCenter.defaultCenter addObserver:self selector:@selector(themeChanged:) name:@"AppleInterfaceThemeChangedNotification" object: nil];

然后在回调方法上写类似

-(void)themeChanged:(NSNotification *) notification 
    [self performSelectorOnMainThread:@selector(themeChangedOnMainThread) withObject:nil waitUntilDone:false];

然后是实际代码:

- (void) themeChangedOnMainThread 
    NSAppearance* appearance = NSApp.effectiveAppearance;
    NSString* name = appearance.name;
    BOOL dark = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]] == NSAppearanceNameDarkAqua;

Borzh 的回答也有帮助,但似乎比其他人更脆弱。

【讨论】:

【参考方案6】:

要了解应用外观是否为深色,请使用以下代码:

+ (BOOL)isDarkMode 
    NSString *interfaceStyle = [NSUserDefaults.standardUserDefaults valueForKey:@"AppleInterfaceStyle"];
    return [interfaceStyle isEqualToString:@"Dark"];

【讨论】:

NSUserDefaults.standardUserDefaults 可能与应用的视图不同。

如何在 PyQt 5.12.2 上启用 macOS 暗模式?

】如何在PyQt5.12.2上启用macOS暗模式?【英文标题】:HowtoenablemacOSdarkmodeonPyQt5.12.2?【发布时间】:2019-06-0711:24:38【问题描述】:例如,thispage声称最新版本的PyQt5应该为我提供macOSMojave的自动暗模式,而无需更改任何内容...除了它... 查看详情

如何在三星互联网浏览器上检测暗模式?

】如何在三星互联网浏览器上检测暗模式?【英文标题】:HowtodetectdarkmodeonSamsungInternetbrowser?【发布时间】:2020-02-2700:21:14【问题描述】:如果可以检测到-是否有可能通过CSS类或JavaScript影响颜色?使用深色阅读器扩展,还可以... 查看详情

如何在macos中打开或关闭mac暗黑模式

...否则本文中的信息适用于装有macOSMojave或更高版本的Mac。如何在Mac上打开或关闭黑暗模式安装了macOSMojave或更高版本时,请执行以下步骤:1.通过从Apple菜单中选择“ 系统偏好设置”或单击Dock中的“ 系统偏好设置... 查看详情

在真实设备上的 XCUI 测试中检测暗模式

】在真实设备上的XCUI测试中检测暗模式【英文标题】:DetectdarkmodeinXCUItestonrealdevices【发布时间】:2021-01-1213:01:13【问题描述】:我正在尝试寻找一种方法来检测手机是否在XCUI测试中处于暗模式。到目前为止,我得到了这个:pri... 查看详情

如何检测 OS X 是不是处于暗模式?

】如何检测OSX是不是处于暗模式?【英文标题】:HowtodetectifOSXisindarkmode?如何检测OSX是否处于暗模式?【发布时间】:2014-10-0203:28:21【问题描述】:我的cocoa应用在新的OSX“黑暗模式”下运行时必须改变其行为。有没有办法检测OS... 查看详情

如何在 mac os 10.14 上安装 vcremote?

】如何在macos10.14上安装vcremote?【英文标题】:Howtoinstallvcremoteonmacos10.14?【发布时间】:2018-12-2900:34:47【问题描述】:我已在MacOSMojave10.14上进行了更新,并想在其上安装vcremote。我运行的命令是sudonpminstall-g--unsafe-permvcremote取自ht... 查看详情

如何在浏览器 JavaScript 中检测 OS X 是不是处于暗模式? [复制]

】如何在浏览器JavaScript中检测OSX是不是处于暗模式?[复制]【英文标题】:HowtodetectifOSXisindarkmodeinbrowserJavaScript?[duplicate]如何在浏览器JavaScript中检测OSX是否处于暗模式?[复制]【发布时间】:2019-09-0509:26:09【问题描述】:类似于... 查看详情

如何在模拟器上启用暗模式?

】如何在模拟器上启用暗模式?【英文标题】:HowtoenableDarkModeontheSimulator?【发布时间】:2020-01-3111:47:50【问题描述】:我正在尝试弄清楚如何在Xcode模拟器上打开新的暗模式。据我所知,它在天黑时会在真实设备上自行开启。有... 查看详情

如何检测浏览器是不是支持暗模式

】如何检测浏览器是不是支持暗模式【英文标题】:Howtodetectifabrowsersupportsdarkmode如何检测浏览器是否支持暗模式【发布时间】:2021-12-2514:34:39【问题描述】:我们可以使用prefers-color-scheme:dark来检测是否激活了暗模式:constisDarkMo... 查看详情

如何在 iOS Xcode Swift Playground 上模拟暗模式

】如何在iOSXcodeSwiftPlayground上模拟暗模式【英文标题】:HowtosimulatedarkmodeoniOSXcodeSwiftPlayground【发布时间】:2020-05-2114:12:33【问题描述】:类似于HowtousedarkmodeinsimulatoriOS13?和HowtoenableDarkModeontheSimulator?,如何在XcodeSwiftPlaygroundLiveVie 查看详情

在miui(小米)中检测暗模式

】在miui(小米)中检测暗模式【英文标题】:Detectdarkmodeinmiui(xiaomi)【发布时间】:2021-04-0610:43:04【问题描述】:我看到了很多关于在堆栈溢出时检测暗模式的问题,例如thisone,并访问了许多中型博客,例如Howtoknowwhenyou’reusingd... 查看详情

使用暗模式修复 OSX 上的 Erlang 观察者

...。窗格的背景颜色和文本非常相似,因此有时难以阅读。如何让Observer在MacOS暗模式下工作?【问题讨论】:【参考方案1】:这个问题似乎与您可能正在运行的wxmac 查看详情

如何在 Mac OS 上使用 Tkinter 获取黑色文件对话框?

】如何在MacOS上使用Tkinter获取黑色文件对话框?【英文标题】:HowtogetablackfiledialogboxusingTkinteronMacOS?【发布时间】:2019-08-2407:04:54【问题描述】:我正在尝试实现一个黑色文件对话框(MacOS暗模式)。我正在使用Tkinter文件对话框... 查看详情

(PHP) 如何检测用户的计算机/浏览器处于暗模式?

】(PHP)如何检测用户的计算机/浏览器处于暗模式?【英文标题】:(PHP)Howtodetectthatuser\'scomputer/browserisinDarkMode?【发布时间】:2019-02-2214:28:27【问题描述】:最近我正在更新我的软件以支持暗模式,以响应研究表明,看着纸白背景... 查看详情

如何在 macOS 上检测 SwiftUI 中的键盘事件?

】如何在macOS上检测SwiftUI中的键盘事件?【英文标题】:HowtodetectkeyboardeventsinSwiftUIonmacOS?【发布时间】:2020-04-1107:44:08【问题描述】:如何在macOS上的SwiftUI视图中检测键盘事件?我希望能够使用击键来控制特定屏幕上的项目,但... 查看详情

如何在 macOS 上检测 SwiftUI 中的键盘事件?

】如何在macOS上检测SwiftUI中的键盘事件?【英文标题】:HowtodetectkeyboardeventsinSwiftUIonmacOS?【发布时间】:2020-04-1107:44:08【问题描述】:如何在macOS上的SwiftUI视图中检测键盘事件?我希望能够使用击键来控制特定屏幕上的项目,但... 查看详情

以编程方式检测 SwiftUI 中的暗模式以显示适当的图像

】以编程方式检测SwiftUI中的暗模式以显示适当的图像【英文标题】:ProgrammaticallydetectdarkmodeinSwiftUItodisplayappropriateImage【发布时间】:2019-12-0807:41:18【问题描述】:在Assets.xcassets中,可以添加其他图像,这些图像将根据外观自动... 查看详情

如何使用 SwiftUI 在 macOS 上可靠地检索窗口的背景颜色?

】如何使用SwiftUI在macOS上可靠地检索窗口的背景颜色?【英文标题】:Howtoreliablyretrieveawindow\'sbackgroundcoloronmacOSwithSwiftUI?【发布时间】:2021-04-2816:54:22【问题描述】:是否有一种Swifty方法可以在macOS上的SwiftUI中检测窗口的背景颜... 查看详情