Как вручную создать динамические (темные / светлые) экземпляры NSImage? - PullRequest
0 голосов
/ 17 октября 2018

Похоже, в macOS 10.14 Mojave, единственный способ создать NSImage экземпляры, которые автоматически рисуют светлую и темную версию, - через каталоги ресурсов и +[NSImage imageNamed:].Тем не менее, мне нужно создавать динамические образы во время выполнения, и, кажется, нет способа сделать это без использования частного API.

Под капотом, похоже, было введено частное свойство _appearanceNameNSImageRep, который каким-то образом используется для выбора правильного представления.Было бы просто создать NSImage с представлениями изображений, которые имеют соответствующий набор _appearanceName, но я бы хотел этого избежать.

Я нашел простой обходной путь (опубликован ниже), но это не таккажется, что работает правильно, когда внешний вид системы меняется (т.е. пользователь переключается со светлого на темный или наоборот) или когда используется в иерархиях представления, у которых свойство appearance установлено на разные виды (например, одно представление жестко запрограммировано на темный режимдругой вид, жестко запрограммированный в светлый режим).

Итак, как я могу вручную создать динамический NSImage, который правильно показывает светлую или темную версию, как это делают изображения из каталога активов?


@implementation NSImage (CustomDynamic)

+ (NSImage *)imageWithLight:(NSImage *)light dark:(NSImage *)dark
{
    if (@available(macOS 10.14, *)) {
        return [NSImage
            imageWithSize:light.size
            flipped:NO
            drawingHandler:^(NSRect dstRect) {
                if ([NSImage appearanceIsDarkMode:NSAppearance.currentAppearance]) {
                    [dark drawInRect:dstRect];
                } else {
                    [light drawInRect:dstRect];
                }
                return YES;
            }
        ];
    } else {
        return light;
    }
}

+ (BOOL)appearanceIsDarkMode:(NSAppearance *)appearance
{
    if (@available(macOS 10.14, *)) {
        NSAppearanceName basicAppearance = [appearance bestMatchFromAppearancesWithNames:@[
            NSAppearanceNameAqua,
            NSAppearanceNameDarkAqua
        ]];
        return [basicAppearance isEqualToString:NSAppearanceNameDarkAqua];

    } else {
        return NO;
    }
}

@end

1 Ответ

0 голосов
/ 17 октября 2018

Оу, оказалось, код, размещенный в вопросе, работает просто отлично!Обработчик рисования на самом деле вызывается , и обрабатывает все ситуации появления.

Однако у меня был код, который масштабировал и кэшировал эти изображения, и это быловсе еще используя древний [image lockFocus]; … [image unlockFocus]; способ рисования изображений вместо использования +[NSImage imageWithSize:flipped:drawingHandler:].

...