NSColor systemColor не меняется при переключении темного / светлого режима - PullRequest
2 голосов
/ 10 июля 2019

Я пытаюсь изменить цвет изображения с переключением темного / светлого режима в 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);
                                                         }];

Iиметь рабочий штраф в подклассе NSButtonCell и переопределять layout, но не может заставить его работать в NSViewController

1 Ответ

3 голосов
/ 12 июля 2019

Сначала проверьте раздел документации «Обновление пользовательских представлений с использованием определенных методов» здесь . Там написано:

Когда пользователь меняет внешний вид системы, система автоматически запрашивает каждое окно и вид для перерисовки. Во время этого процесса система вызывает несколько известных методов для macOS и iOS, перечисленных в следующей таблице, для обновления вашего контента. Система обновляет среду признаков перед вызовом этих методов, поэтому, если вы внесете в них все изменения, чувствительные к внешнему виду, ваше приложение обновится правильно.

Однако в этой таблице нет методов 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, которое не зависит от внешнего вида системы и обновляется Какао в перечисленных выше методах. В любом другом месте вам нужно будет проверить, правильно ли это. Идиоматический путь, опять же, через представление 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]];
    }
}
...