Остановить очистку drawView NSView перед рисованием?(lockFocus больше не работает на macOS 10.14) - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть анимация с использованием двух представлений, где я вызываю lockFocus и получаю графический контекст второго NSView с [[NSGraphicsContext currentContext] graphicsPort] и рисую.Это работало нормально до MacOS 10,14 (Мохаве).

Нашли ссылку здесь: https://developer.apple.com/videos/play/wwdc2018/209/

В 22:40 они рассказывают об изменившемся «устаревшем» резервном хранилище.Вышеупомянутый lockFocus и шаблон контекста были большими на экране, говоря, что это больше не будет работать.И это правда.lockFocus () по-прежнему работает и даже дает вам правильный NSView, но любой рисунок через контекст больше не работает.

Конечно, правильный способ рисования в представлении - это drawRect из Nsview.Поэтому я переставил все, чтобы сделать именно это.Это работает, но drawRect уже автоматически очистил «грязную» область для вас перед вызовом drawRect.Если вы использовали setNeedsDisplayInRect: он даже очистит только эти области для вас.Но это также очистит области, состоящие из более чем одного грязного прямоугольника.И он очищает прямоугольные области, в то время как я рисую округлые объекты, поэтому я получаю слишком много убранного (черная область):

black area is cleared

Есть лиспособ помешать drawRect очистить фон?

Если нет, мне придется вместо этого переключиться на использование слоя NSView и использовать updateLayer, или что-то в этом роде.

Update :Я играю с использованием слоев NSView, возвращая TRUE для WantLayer и wantUpdateLayer, и реализую:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

То есть только , вызываемый, когда я делаю:

- (BOOL) wantsLayer { return YES; }
- (BOOL) wantsUpdateLayer { return NO; } 

и используют setNeedsDisplayInRect: или setNeedsDisplay:

, что действительно делает drawRect больше не вызываемым, но такое же автоматическое стирание фона уже произошло ко времени вызова моего drawLayer :.Так что я не сделал никакого прогресса там.Это действительно эффект setNeedsDisplayInRect, а не мой рисунок.Просто вызов setNeedsDisplayInRect вызывает эти стирания.

Если вы установите:

- (BOOL) wantsLayer { return YES; }
- (BOOL) wantsUpdateLayer { return YES; } 

, то вызывается только:

- (void) updateLayer

, который не предоставляет мне контекст для рисования.

У меня была некоторая надежда на:

self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawNever;

Документ NSView говорит:

Оставьте содержимое слоя в покое.Никогда не отмечайте слой как требующий отображения, и не рисуйте содержимое вида на слой.Вот как обрабатываются слои, созданные разработчиком (представления с размещением слоев).

, и он делает именно это.Он не уведомляет вас и не вызывает делегатов.

Есть ли способ получить полный контроль над содержимым NSView / layer?

UPDATE2019-JAN-27: NSView имеет метод makeBackingLayer, который, я думаю, не существует ни за что.Реализовал это, и, кажется, работает, в принципе, но на экране ничего не отображается.Отсюда следующий вопрос: nsview-makebackinglayer-with-calayer-subclass-display-no-output

1 Ответ

0 голосов
/ 27 января 2019

Используя NSView lockFocus и unlockFocus или пытаясь получить доступ к графическому содержимому окна, напрямую не работающему в macOS 10.14.

Вы можете создать объект NSBitmapImageRep и обновить чертеж в этом контексте.

Пример кода:

- (void)drawRect:(NSRect)rect {
    if (self.cachedDrawingRep) {
        [self.cachedDrawingRep drawInRect:self.bounds];
    }
}

- (void)drawOutsideDrawRect {
     NSBitmapImageRep *cmap = self.cachedDrawingRep;
    if (!cmap) {
        cmap = [self bitmapImageRepForCachingDisplayInRect:self.bounds];
        self.cachedDrawingRep = cmap;
    }
    NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:cmap];
    NSAssert(ctx, nil);
    [NSGraphicsContext setCurrentContext:ctx];

    // Draw code here

    self.needsDisplay = YES;
 }
...