MacOS Sierra: почему добавление NSScrollView к подпредставлению изменяет (/ повреждает?) Порядок рисования суперпредставлений? - PullRequest
1 голос
/ 24 января 2020

В моем приложении и в более простом тестовом примере добавление NSScrollView к NSView внутри иерархии представления, по-видимому, нарушает порядок рисования всей иерархии представления (выше и вне этого NSScrollView). Я испытываю это только на MacOS Sierra, а не на Mojave или более поздней (у меня нет High Sierra для тестирования), и, к сожалению, мне нужно исправить это на Sierra, несмотря на то, что я использую Mojave (что означает, что у меня нет удобной возможности выполнять под XCode). Хотя я знаю, что Sierra - это старые новости, я подозреваю, что это как-то моя ошибка, поскольку корректность рендеринга представлений является фундаментальной, я не нахожусь в сложной ситуации, а Sierra 10.12.6 - довольно зрелый код.

Может ли кто-нибудь дать мне достаточное представление о том, что я ошибаюсь, чтобы я мог достичь своего намеченного дизайна в Sierra, который заключается в том, чтобы метка (NSTextField) сидела визуально поверх другого пользовательского представления Canvas, который в свою очередь встраивает scrollView несвязанного содержимого?

Симптом проблемы заключается в том, что Sierra неправильно рисует aws Метка ниже Canvas, где тот же код на Мохаве др aws Ярлык правильно поверх Холст. В моем простейшем тестовом примере у меня есть Canvas (мой пользовательский вид) и моя метка stati c, предварительно определенная в окне в Интерфейсном Разработчике, с Меткой позже, чем Canvas в порядке Представления (больше "сверху" в стек рисования):

Interface Builder: Label ontop MyCanvas

В awakeFromNib MyCanvas я программно создаю scrollView, добавляю к нему изображение и затем добавляю его в Canvas:

@implementation MyCanvas

- (void)awakeFromNib { 

    NSImageView *image = [NSImageView imageViewWithImage:[NSImage imageNamed:@"bigRedX"]];
    image.frame = CGRectInset(self.frame, 20.0, 5.0);

    #if 1
        /* Embed image in new scrollView embedded in MyCanvas. MyCanvas now draws ontop higher views in Sierra! */
        NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:self.frame];
        scrollView.documentView = image;
        [self addSubview: scrollView];
    #else
        /* Embed image directly into MyCanvas. MyCanvas stills draws correctly beneath higher views in Sierra! */
        [self addSubview: image];
    #endif

    ...
}

Запустив результат и изменив размеры окна таким образом, чтобы они сошлись (холст прилипает к верхним / левым границам окна, метка придерживается снизу / справа), я вижу следующее правильное поведение в Mojave, Label ontop of Canvas: Mojave image - good order

И соответствующее некорректное поведение в Sierra, Canvas ontop Label:

Sierra image - bad order

фактический порядок представлений в суперпредставлении окна идентичен для [NSView _subtreeDescription]. Mojave включает несколько новых подпредставлений для NSImageView, NSScrollView и NSClipView NSScrollView, но на обеих платформах два представления верхнего уровня находятся в одном и правильном порядке: NSTextField находится после (поверх) MyCanvas.

Mojave:

Unmanaged<AnyObject>(_value: [   A      w   ] h=--- v=--- NSView 0x100eb1350 f=(0,0,346,295) b=(-) => <_NSViewBackingLayer: 0x10ad86970>
  [   AF     w   ] h=--& v=&-- MyCanvas 0x100ef7260 f=(34,25,277,250) b=(-) => <_NSViewBackingLayer: 0x10ad7a280>
    [   AF O   w   ] h=--- v=--- NSScrollView 0x100ef8220 f=(34,33,277,250) b=(-) => <_NSViewBackingLayer: 0x10ad79940>
      [   A      w   ] h=--- v=--- _NSScrollViewContentBackgroundView 0x10d6f4290 f=(0,0,277,250) b=(-) => <_NSViewBackingLayer: 0x10ad46800>
        [   A      w   ] h=--- v=--- NSVisualEffectView 0x10d6f7c40 f=(0,0,277,250) b=(-) => <_NSViewBackingLayer: 0x10ad2bc90>
      [   A      w   ] h=-&- v=-&- NSClipView 0x100ef9110 f=(0,0,277,250) b=(54,38,-,-) => <_NSClipViewBackingLayer: 0x10ad903e0>
        [   A      w   ] h=--- v=--- NSImageView 0x100efa6e0 "<NSImage 0x100fb6120 Name=bigRedX Size={180, 180} Reps=(
    "NSBitmapImageRep 0x10108aeb0 Size={180, 180} ColorSpace=DELL 2007FP colorspace BPS=8 BPP=32 Pixels=180x180 Alpha=NO Planar=NO Format=0 CurrentBacking=<CGImageRef: 0x100ea1260> CGImageSource=0x101507b70"
)>" f=(54,38,237,240) b=(-) => <_NSViewBackingLayer: 0x10adb3ea0>
          [   A      w   ] h=--- v=--- _NSImageViewSimpleImageView 0x100efb540 f=(29,30,180,180) b=(-) => <_NSViewBackingLayer: 0x1010e7a80>
  [   AF     w   ] h=&&- v=--& NSTextField 0x100e66f70 "Static Label" f=(125.5,42,213.5,16) b=(-) => <NSTextLayer: 0x10adabcb0>
A=autoresizesSubviews, C=canDrawConcurrently, D=needsDisplay, F=flipped, G=gstate, H=hidden (h=by ancestor), L=needsLayout (l=child needsLayout), U=needsUpdateConstraints (u=child needsUpdateConstraints), O=opaque, P=preservesContentDuringLiveResize, S=scaled/rotated, W=wantsLayer (w=ancestor wantsLayer), V=needsVibrancy (v=allowsVibrancy), #=has surface
)

Sierra:

Unmanaged<AnyObject>(_value: [   A        U ] h=--- v=--- NSView 0x7fd3f4fe9920 f=(0,0,339,319) b=(-) TIME drawRect: min/mean/max 0.00/0.00/0.00 ms
  [   AF       U ] h=--& v=&-- MyCanvas 0x7fd3f9f8af50 f=(34,49,277,250) b=(-) TIME drawRect: min/mean/max 0.00/0.00/0.00 ms
    [   AF O   W U#] h=--- v=--- NSScrollView 0x7fd3f9f22a40 f=(34,33,277,250) b=(-) => <_NSViewBackingLayer: 0x7fd3f4eef4c0> TIME drawRect: min/mean/max 0.00/0.00/0.00 ms
      [   A  O   w U ] h=--- v=--- NSClipView 0x7fd3f9f4cab0 f=(0,0,277,250) b=(54,38,-,-) => <_NSClipViewBackingLayer: 0x7fd3f4ee0c80> TIME drawRect: min/mean/max 0.00/0.00/0.00 ms
        [   A      w U ] h=--- v=--- NSImageView 0x7fd3f4de6320 "<NSImage 0x7fd3f4de6020 Name=bigRedX Size={180, 180} Reps=(
    "NSBitmapImageRep 0x7fd3f9f213f0 Size={180, 180} ColorSpace=DELL 2007FP colorspace BPS=8 BPP=32 Pixels=180x180 Alpha=NO Planar=NO Format=0 CurrentBacking=<CGImageRef: 0x7fd3f9901200> CGImageSource=0x7fd3f9f973f0"
)>" f=(54,38,237,240) b=(-) => <_NSViewBackingLayer: 0x7fd3f4ef40c0> TIME drawRect: min/mean/max 0.00/0.00/0.00 ms
  [   AF       U ] h=&&- v=--& NSTextField 0x7fd3f9bd81e0 "Static Label" f=(122,42,210,16) b=(-) TIME drawRect: min/mean/max 0.00/0.00/0.00 ms
A=autoresizesSubviews, C=canDrawConcurrently, D=needsDisplay, F=flipped, G=gstate, H=hidden (h=by ancestor), L=needsLayout (l=child needsLayout), U=needsUpdateConstraints (u=child needsUpdateConstraints), O=opaque, P=preservesContentDuringLiveResize, S=scaled/rotated, W=wantsLayer (w=ancestor wantsLayer), V=needsVibrancy (v=allowsVibrancy), #=has surface
)

Наконец, я указываю подозрительным пальцем на NSScrollView, потому что, если я откажусь от scrollView и вместо этого вставлю bigRedX непосредственно в MyCanvas вместо того, чтобы встраивать его в scrollView и встраивать его в myCanvas, Canvas, содержащий bigRedX dr aws, находится под меткой на Sierra и Mojave. (Этот случай отличается по кодам только изменением #if 1 на #if 0 во фрагменте выше.) И я подозреваю, что это проблема в реальном порядке рисования, а не в обрезке, потому что если я заменю MyCanvas прозрачным фоном, а не непрозрачным Я могу видеть лейбл "под" Холстом в Сьерре, где он должен быть сверху. Но как я могу добиться того, чтобы это происходило, даже если у меня на холсте есть scrollView?

Спасибо за любой свет, который вы можете пролить!

...