GravityScore
GravityScore

Reputation: 385

How to add a CALayer to an NSView on Mac OS X

I'm trying to learn how to use and implement CALayer in a Mac Objective-C application, but I can't seem to probably do the most basic thing - add a new layer and set its background colour/frame size. Can anyone see what is wrong with my code?

CALayer *layer = [CALayer layer];
[layer setFrame:CGRectMake(0, 0, 100, 100)];
[layer setBackgroundColor:CGColorCreateGenericRGB(1.0, 0.0, 0.0, 1.0)];
[self.layer addSublayer:layer];
[layer display];

I put this in the - (void)drawRect:(NSRect)rect method of my custom NSView subclass, but when I run the application, it just shows a blank view, with no background colour or evidence of the layer I created.

Upvotes: 20

Views: 17912

Answers (4)

MH175
MH175

Reputation: 2334

Updated info (Swift): first call view.makeBackingLayer() then set wantsLayer to true.

https://developer.apple.com/documentation/appkit/nsview/1483695-wantslayer

Upvotes: 0

Amber Haq Dixon
Amber Haq Dixon

Reputation: 614

You need to make a call to the "setWantsLayer" method.

Check out the following documentation for the description for setWantsLayer: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html

In a nutshell, your view needs to be layer-hosting view. Because it is a layer-hosting view, you should interact with the layer, and NOT interact with the view itself and don't add subviews to it.

[self setLayer:[CALayer new]];
[self setWantsLayer:YES];     // the order of setLayer and setWantsLayer is crucial!
[self.layer setBackgroundColor:[backgroundColor CGColor]];

Upvotes: 6

omz
omz

Reputation: 53551

First of all, you don't want to add a layer in the drawRect: method of a view, this gets called automatically by the system and you'd probably end up with a lot more layers than you actually want. initWithFrame: or initWithCoder: (for views that are in a nib file) are better places to initialize your layer hierarchy.

Furthermore, NSViews don't have a root layer by default (this is quite different from UIView on iOS). There are basically two kinds of NSViews that use a layer: layer-backed views and layer-hosting views. If you want to interact with the layer directly (add sublayers etc.), you need to create a layer-hosting view.

To do that, create a CALayer and call the view's setLayer: method. Afterwards, call setWantsLayer:. The order is important, if you'd call setWantsLayer: first, you'd actually create a layer-backed view.

Upvotes: 60

atreat
atreat

Reputation: 4403

Put this out of the drawRect. I normally put my layer setup in either the init method or the viewDidLoad.

Otherwise anytime the view is drawn a new layer is added and allocated. Also I've never used the [layer display] line before. The docs actually tell you not to call this method directly.

Upvotes: 1

Related Questions