在macOS 10.14中,用户可以选择采用系统范围的亮或暗外观,我需要根据当前模式手动调整一些颜色。
答案 0 :(得分:14)
由于您通常通过effectiveAppearance
获得的实际外观对象是复合外观,因此直接询问其名称可能不是一个可靠的解决方案。
请求currentAppearance
通常也不是一个好主意,因为视图可能已显式设置为亮模式,或者您想知道{{1}之外的视图是亮还是暗},在模式切换后您可能会得到不正确的结果。
我想出的解决方案如下:
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
(最好选择一个Apple将来不太可能使用的名称,例如添加供应商前缀)。
答案 1 :(得分:12)
我已使用当前外观检查系统是否为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
答案 2 :(得分:4)
雨燕4
func isDarkMode(view: NSView?) -> Bool {
if #available(OSX 10.14, *) {
if let appearance = view?.effectiveAppearance ?? NSAppearance.current {
return (appearance.name == .darkAqua)
}
}
return false
}
更新:
func isDarkMode(view: NSView) -> Bool {
if #available(OSX 10.14, *) {
return view.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
}
return false
}
答案 3 :(得分:1)
一个视图实际上有8个可能的appearances,其中4个是普通使用的。也就是说,
NSAppearanceNameAqua
灯光模式,NSAppearanceNameDarkAqua
黑暗模式,NSAppearanceNameAccessibilityHighContrastAqua
增强对比度的灯光模式(通过辅助功能设置),NSAppearanceNameAccessibilityHighContrastDarkAqua
暗模式,对比度增强。 直接比较
appearance.name == NSAppearanceNameDarkAqua;
对比度增强,可能无法检测到黑暗模式。因此,请始终使用bestMatchFromAppearancesWithNames
。
最好考虑高对比度的外观,以实现更好的可访问性。
答案 4 :(得分:0)
要了解 app 外观是否为深色,请使用下一个代码:
+ (BOOL)isDarkMode {
NSString *interfaceStyle = [NSUserDefaults.standardUserDefaults valueForKey:@"AppleInterfaceStyle"];
return [interfaceStyle isEqualToString:@"Dark"];
}
答案 5 :(得分:0)
对我来说,如果我想要一个全局状态,而不是每个视图,并且我没有访问该视图的权限,并且希望收到更新的通知,这些答案都不起作用。
解决方案是在主线程中请求NSApp.effectiveAppearance
,或者至少在当前回调方法返回系统后 。
因此,首先我必须按照SaúlMoreno 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的回答也有所帮助,但似乎比其他答案更脆弱。