dark/light 模式切换时 NSColor systemColor 没有改变

NSColor systemColor not changing when dark/light mode switched

我正在尝试通过在 NSViewController 中切换 dark/light 模式来更改图像的颜色。 我正在使用此代码更改图像的颜色:

- (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]];

但系统颜色似乎总是returns相同的 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 子类和覆盖 layout 中工作正常,但无法在 NSViewController

中工作

首先,检查文档部分 "Update Custom Views Using Specific Methods" here。它说:

When the user changes the system appearance, the system automatically asks each window and view to redraw itself. During this process, the system calls several well-known methods for both macOS and iOS, listed in the following table, to update your content. The system updates the trait environment before calling these methods, so if you make all of your appearance-sensitive changes in them, your app updates itself correctly.

但是,table 中没有列出 NSViewController 方法。

由于视图的外观可以独立于当前或 "system" 外观,因此对视图控制器中的外观变化做出反应的最佳方式是 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]];
    }
}