How to add a CALayer to an NSView on Mac OS X
Asked Answered
T

4

20

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.

Teresiateresina answered 4/3, 2012 at 3:10 Comment(0)
G
60

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.

Grind answered 4/3, 2012 at 5:1 Comment(1)
Still relevant. Thanks! Mac os programming is crazy 😁Belemnite
M
6

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]];
Martguerita answered 2/7, 2013 at 22:2 Comment(0)
U
1

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.

Uriah answered 4/3, 2012 at 3:35 Comment(2)
Thanks for replying, but this still didn't change anything. The view is still blank. BTW I am trying to create a mac os x application, so I can't call viewDidLoad.Teresiateresina
Oh sorry, I missed that. There must be some initialization method that occurs when the window loads. I'm not familiar with Mac programming but I know iOS-wise that QuartzCore needs to be imported for CALayer to be applicable(I don't want to assume you know this). What you could also try is to manipulate the root layer directly to see if that is working ([self.layer setBackgroundColor:...]).Uriah
C
0

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

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

Cliffordclift answered 10/9, 2020 at 23:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.