NSColor系统切换暗/亮模式时颜色不改变 [英] NSColor systemColor not changing when dark/light mode switched

查看:217
本文介绍了NSColor系统切换暗/亮模式时颜色不改变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过NSViewController中的暗/亮模式切换来更改图像的颜色. 我正在使用以下代码来更改图像的颜色:

I'm trying to change the colour of an image with the switching of dark/light mode in an NSViewController. I'm using this code for changing the colour of the image:

- (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值.

but it seems the system color always returns the same RGB values.

我也尝试过监听通知AppleInterfaceThemeChangedNotification,但是即使在这里,似乎RGB值也保持不变.

I've also tried listening for the notification AppleInterfaceThemeChangedNotification but even in here it seems the RGB values stay the same 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

I have the working fine in an NSButtonCell sublass and overriding layout but can't get it working in an NSViewController

推荐答案

首先,查看文档部分使用特定方法更新自定义视图"

First, check the documentation section "Update Custom Views Using Specific Methods" here. It says:

当用户更改系统外观时,系统会自动要求每个窗口和视图重绘自身.在此过程中,系统将为macOS和iOS调用下表中列出的几种众所周知的方法来更新您的内容.系统会在调用这些方法之前更新特征环境,因此,如果您对它们进行了所有外观敏感的更改,则应用程序会正确更新自己.

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.

但是,该表中没有列出NSViewController方法.

However, there are no NSViewController methods listed in that table.

由于视图的外观可以独立于当前或系统"外观,因此对视图控制器中的外观变化做出反应的最佳方法是对视图的effectiveAppearance属性进行KVO或在[NSView viewDidChangeEffectiveAppearance]中执行操作

Since the view's appearance can be independent of the current or "system" appearance, the best way to react to appearance changes in your view controller is to either KVO the view's effectiveAppearance property, or to do something in [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 has a currentAppearance property which is independent of the system appearance, and updated by Cocoa in the methods listed above. Everywhere else, you will need to check that is correct yourself. The idiomatic way is, again, via the view's effectiveAppearance:

[NSAppearance setCurrentAppearance:someView.effectiveAppearance];

因此,在您的情况下,以下内容对我来说很有效:

So, in your case, the following works well for me:

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

这篇关于NSColor系统切换暗/亮模式时颜色不改变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆