macos - NSColor systemColor 在暗/亮模式切换时不会改变
问题描述
我正在尝试通过在NSViewController
. 我正在使用此代码更改图像的颜色:
- (NSImage *)image:(NSImage *)image withColour:(NSColor *)colour
{
NSImage *img = image.copy;
[img lockFocus];
[colour set];
NSRect imageRect = NSMakeRect(0, 0, img.size.width, img.size.height);
NSRectFillUsingOperation(imageRect, NSCompositingOperationSourceAtop);
[img unlockFocus];
return img;
}
我试过从viewWillLayout
self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];
但似乎系统颜色总是返回相同的 RGB 值。
我也尝试过收听通知AppleInterfaceThemeChangedNotification
,但即使在这里,RGB 值似乎也保持不变1.000000 0.231373 0.188235
。
[[NSDistributedNotificationCenter defaultCenter] addObserverForName:@"AppleInterfaceThemeChangedNotification"
object:nil
queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
NSLog(@"AppleInterfaceThemeChangedNotification");
self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];
NSColorSpace *colorSpace = [NSColorSpace sRGBColorSpace];
NSColor *testColor = [[NSColor systemBlueColor] colorUsingColorSpace:colorSpace];
CGFloat red = [testColor redComponent];
CGFloat green = [testColor greenComponent];
CGFloat blue = [testColor blueComponent];
NSLog(@"%f %f %f", red, green, blue);
}];
我在NSButtonCell
sublass 和压倒一切的工作正常,layout
但不能让它在NSViewController
解决方案
首先,在此处查看文档部分“使用特定方法更新自定义视图” 。它说:
当用户改变系统外观时,系统会自动要求每个窗口和视图重新绘制自己。在此过程中,系统会调用下表中列出的适用于 macOS 和 iOS 的几种众所周知的方法来更新您的内容。系统会在调用这些方法之前更新 trait 环境,因此如果您在其中进行所有外观敏感的更改,您的应用程序会正确更新自身。
但是,NSViewController
该表中没有列出任何方法。
由于视图的外观可以独立于当前或“系统”外观,因此对视图控制器中的外观变化做出反应的最佳方法是 KVO 视图的effectiveAppearance
属性,或者在[NSView viewDidChangeEffectiveAppearance]
.
- (void)viewDidLoad
{
[self addObserver:self forKeyPath:@"view.effectiveAppearance" options:0 context:nil];
}
// ...
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
if ([keyPath isEqualToString:@"view.effectiveAppearance"])
{
// ...
NSAppearance
具有currentAppearance
独立于系统外观的属性,并由 Cocoa 在上面列出的方法中更新。在其他任何地方,您都需要自己检查是否正确。再次,惯用的方式是通过视图effectiveAppearance
:
[NSAppearance setCurrentAppearance:someView.effectiveAppearance];
因此,就您而言,以下内容对我很有效:
- (void)viewDidLoad
{
[super viewDidLoad];
[self addObserver:self forKeyPath:@"view.effectiveAppearance" options:0 context:nil];
}
-(void)viewDidLayout
{
self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"view.effectiveAppearance"])
{
[NSAppearance setCurrentAppearance:self.view.effectiveAppearance];
self.help1Image.image = [self image:self.help1Image.image withColour:[NSColor systemRedColor]];
}
}
推荐阅读
- python - PIP 安装正确,但执行时不执行任何操作
- ms-access - 链接的 DB2 表不接受 MSAccess 查询中的日期条件
- csv - 如何验证 CSV 文件的标题是否与我的结构匹配?
- ruby-on-rails - 文件在 rails 中始终以 PDF 格式下载
- php - 序列化问题:对象键 <> 被 php cURL 剥离
- python - 不知道如何从双对“ab”解码为“a”
- node.js - 如何使用 json-server 部署 reactJS 应用程序
- python - 使用 python 和 kivy 在 pyinstaller 中生成的 exe 不起作用
- python - Tensorflow“匹配”两个张量
- microsoft-teams - 识别 MS Teams 上的“转移”呼叫