首页 > 解决方案 > 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);
                                                         }];

我在NSButtonCellsublass 和压倒一切的工作正常,layout但不能让它在NSViewController

标签: macosnscolormacos-darkmode

解决方案


首先,在此处查看文档部分“使用特定方法更新自定义视图” 。它说:

当用户改变系统外观时,系统会自动要求每个窗口和视图重新绘制自己。在此过程中,系统会调用下表中列出的适用于 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]];
    }
}

推荐阅读