views:

77

answers:

1

I'm having trouble with a layer hosting view. This version of initWithFrame: works as expected (the view is filled black) providing 'Wants Core Animation Layer' is selected in Interface Builder:

- (id)initWithFrame:(NSRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        [self setWantsLayer:YES];
        [[self layer] setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)];    
        [[self layer] setContents:[NSImage imageNamed:NSImageNameBonjour]];
    }
    return self;
}

I want to be able to configure the view programmatically so I want to remove the reliance on Interface Builder. Below is the second version which is meant to achieve this. This doesn't work. The view stays the same color as the parent view:

- (id)initWithFrame:(NSRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        CALayer *rootLayer = [CALayer layer]; //Added this line,
        [self setLayer:rootLayer];  //and this line only
        [self setWantsLayer:YES];
        [[self layer] setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)];    
        [[self layer] setContents:[NSImage imageNamed:NSImageNameBonjour]];
    }
    return self;
}

I copied the code from the documentation and searched the web and all examples I found did exactly this, but it's not working!

What am I doing wrong?

A: 

The problem is not to do with layers but when in the views life cycle the layers are initialized.

If the view is being created in code and being added to a window which has already been drawn to the screen then the initWithFrame: method can be used to create the layers. However this will not work if the view is being initalized from a NIB. When being initalized from a NIB the initWithFrame: method will be called before the parent window is fully initalized which results in the layers not displaying. When the window is being stored in a NIB awakeFromNib can be used instead of initWithFrame: to ensure the layers are initialized correctly.

Of course having two points in the code where the layers could be created is ugly. viewDidMoveToSuperview is called at a useful point in both of the above use cases. Checks should be added to viewDidMoveToSuperview to ensure that the layers are only created once.

(Mental note - If something doesn't make sense and you feel you need to ask on Stack Overflow it's a good sign that you need some sleep.)

Benedict Cohen