1
votes

My situation:

I have a single window with a content view (NSView), which has several subviews (plain NSControl subclasses; not important, just for testing) scattered around it. For part of the end effect I am trying to achieve, I want to place a semi-transparent black CALayer overlaying the whole window's content view, and be able to make it invisible (either by hiding it or removing it, doesn't matter) when a certain event is triggered, revealing the NSViews in full clarity.

For testing purposes, I place a small semi-transparent black CALayer covering only some/parts of the subviews (the controls) in the main content view, like so:

(doh, had screenshots but can not post images as a new user. You'll have to use your imagination.)

Simple enough. So then all I tried to do was to check that it hides/removes itself properly. Then came the problem. Any attempt at hiding, removing or reducing the black layer or reducing its transparency to 0 causes all of the window's subviews to become erased, with a result looking like this:

(a window with a completely blank grey [the default window bg colour] content view)

Here's the meat of the code, in the main application call which has a reference to the main window:

    // I set up my main view in a nib, which I load and will add
    // to the app window as the main content view
    NSViewController * controller = [[NSViewController alloc]
    initWithNibName:@"InterfaceTesting" bundle:nil];

    NSView * view = [controller view];

    // enable layers, grab root
    [view setWantsLayer:YES];       
    CALayer * rootLayer = [view layer];

    // set up black square
    CALayer * blackLayer = [CALayer layer];
    [blackLayer setFrame:NSMakeRect(150, 150, 100, 100)];
    [blackLayer setBackgroundColor:CGColorCreateGenericRGB(0,0,0,0.5)];
    [rootLayer addSublayer:blackLayer];

    // hide all sublayers of root (ie the black square)     
    for (CALayer * layer in [[view layer] sublayers])
        [layer setHidden:YES];

    // add to main window
    [self.window setContentView:view];

As I mentioned before, replacing [layer setHidden:YES] with [layer setOpacity:0] has the same effect of erasing the content view, as does removing the blackLayer altogether (by calling removeFromSuperlayer and also by trying to set its superlayer to nil). More interesting still, if I set the opacity of the black sublayer square to something between 0 and 1 - 0.5, say - then all of the content view's subviews' opacities reduces accordingly.

So I'm rather baffled here, as I don't understand why hiding/removing or reducing opacity on the small black CALayer is affecting all the subviews in the view it is a part of, even those it doesn't cover. Any help is much appreciated.

Edit: Well I've discovered that the contentView's top layer in fact has a sublayer not only for the black square I manually added, but for every subview as well (whether originating from the nib or manually created by me after loading the view from the nib), hence why they were all fading/disappearing when I thought I was just operating on the black box. But what I still don't know is why there are layers for all the subviews, where they came from, and how to get rid of them (again, all attempts to remove them - via removeFromSuperlayer, setting to nil, etc - fail.

1

1 Answers

1
votes

Subviews (controls) have layers which are set as sublayers of the parent view layer. So looping through all the sublayers also acts on these subview layers.