我的Cocoa应用程序在新的OS X“暗黑模式”下运行时必须更改其行为。
有没有一种方法可以检测操作系统的样式是否设置为此模式?
目前好像没有一种可靠的方法来检测 Cocoa 是否处于暗黑模式下,但是您可以使用 defaults read
命令来检查 macOS 系统是否启用了暗黑模式。
defaults read -g AppleInterfaceStyle
返回Dark
(暗色模式)或返回域对不存在。
编辑:
如Ken Thomases所说,您可以通过NSUserDefaults访问.GlobalPreferences,因此
NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
如果 osxMode 的值是 nil
,那么它不在暗黑模式中,但如果 osxMode 的值是 @"Dark"
,则它处于暗黑模式中。defaults
命令只是 CFPreferences
API 的一个包装器,NSUserDefaults
也是如此。因此,您可以使用这些 API 中的任何一个,而不是调用 defaults
。 - Ken Thomasesdefaults read -g AppleInterfaceStyle
命令会返回“Dark”,否则会返回“The domain/default pair of (kCFPreferencesAnyApplication, AppleInterfaceStyle) does not exist”。这个结果相当不可预测。:) - VictorSwift 2 -> 字符串 ("暗", "亮")
let appearance = NSUserDefaults.standardUserDefaults().stringForKey("AppleInterfaceStyle") ?? "Light"
Swift 3 -> 枚举类型(暗色,明亮)
enum InterfaceStyle : String {
case Dark, Light
init() {
let type = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") ?? "Light"
self = InterfaceStyle(rawValue: type)!
}
}
let currentStyle = InterfaceStyle()
init()
方法! - SilverWolfNSAppearanceCustomization
方法effectiveAppearance
来检测,通过检查darkAqua
来确定。extension NSView {
var isDarkMode: Bool {
if #available(OSX 10.14, *) {
if effectiveAppearance.name == .darkAqua {
return true
}
}
return false
}
}
[NSAppearance.Name.darkAqua,NSAppearance.Name.vibrantDark] .contains(effectiveAppearance.name)
来检查两种暗色外观。 - GP89如果你不想处理枚举和switch语句,你也可以将它包装在一个布尔值中:
/// True if the application is in dark mode, and false otherwise
var inDarkMode: Bool {
let mode = UserDefaults.standard.string(forKey: "AppleInterfaceStyle")
return mode == "Dark"
}
适用于Swift 4.2
要在新的macOS Catalina上工作,您需要将AppleInterfaceStyle
与这个新值AppleInterfaceStyleSwitchesAutomatically
结合使用。
以下是一些伪代码,说明如何操作:
theme = light //default is light
if macOS_10.15
if UserDefaults(AppleInterfaceStyleSwitchesAutomatically) == TRUE
if UserDefaults(AppleInterfaceStyle) == NIL
theme = dark // is nil, means it's dark and will switch in future to light
else
theme = light //means it's light and will switch in future to dark
endif
else
if UserDefaults(AppleInterfaceStyle) == NIL
theme = light
else
theme = dark
endif
endif
else if macOS_10.14
if UserDefaults(AppleInterfaceStyle) == NIL
theme = light
else
theme = dark
endif
endif
您可以在此处查看一个 macOS 示例应用程序:https://github.com/ruiaureliano/macOS-Appearance。
(免责声明:本示例应用程序的作者为我自己。)
extension NSView {
var hasDarkAppearance: Bool {
if #available(OSX 10.14, *) {
switch effectiveAppearance.name {
case .darkAqua, .vibrantDark, .accessibilityHighContrastDarkAqua, .accessibilityHighContrastVibrantDark:
return true
default:
return false
}
} else {
switch effectiveAppearance.name {
case .vibrantDark:
return true
default:
return false
}
}
}
}
if #available(OSX 10.14, *) {
inputTextView.textColor = (NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua ? NSColor.white : NSColor.black)
}
draw(_ dirtyRect:)
中按如下方式检索颜色:let strokeColour = NSColor(named: NSColor.Name("gridColour")) ?? NSColor.black
NSColor(named:)
的可选类型。检查暗模式的唯一安全方式是使用以下方法:
let viewUsesDarkMode: Bool
if #available(OSX 10.14, *) {
viewUsesDarkMode = view.effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua
} else {
viewUsesDarkMode = false
}
这是唯一适用于所有情况的解决方案。无论您的视图外观是否混合,或者您允许应用程序使用与系统默认不同的外观,或者您配置系统使用高对比度外观。
if #available(macOS 10.14, *) { if view.effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua || view.effectiveAppearance.bestMatch(from: [.vibrantLight, .vibrantDark]) == .vibrantDark { viewUsesDarkMode = true } else { viewUsesDarkMode = false } } else { viewUsesDarkMode = false }
- SouthernYankee65bestMatch
从提供的选项中选择最接近的外观。在这种情况下,如果effectiveAppearance
碰巧是.vibrantDark
,则结果仍将是.darkAqua
。 - Jakob Egger2020 | SWIFT 5.1:
@Environment(\.colorScheme) var scheme
在主题更改的情况下,不会更新SwiftUI。需要实现额外的逻辑来更新视图:
#available(OSX 10.14, *)
static private var isLight: Bool { NSApp.effectiveAppearance.name == NSAppearance.Name.aqua }
#available(OSX 10.14, *)
static private var isDark: Bool { NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua }
AppleInterfaceThemeChangedNotification
分布式通知添加观察者,然后从那里开始。 - red_menace
NSScreenColorSpaceDidChangeNotification
或检查NSScreen
的colorSpace
属性吗?我现在用的是Mav,无法检查。 - Warren Burton