views:

24

answers:

2

I have my very own minimal view class with this:

- (void) awakeFromNib
{
    NSLog(@"awakeFromNib!");
    [self.layer setDelegate:self];
    [self.layer setFrame:CGRectMake(30, 30, 250, 250)];
    self.layer.masksToBounds = YES;
    self.layer.cornerRadius = 5.0;
    self.layer.backgroundColor = [[UIColor redColor] CGColor];
    [self setNeedsDisplay];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    NSLog(@"drawing!");
}

drawLayer:inContext never get called, although I can see the layer as red, rounded corner rectangle. What am I missing?

EDIT: from Apple docs

You can draw content for your layer, or better encapsulate setting the layer’s content image by creating a delegate class that implements one of the following methods: displayLayer: or drawLayer:inContext:.

Implementing a delegate method to draw the content does not automatically cause the layer to draw using that implementation. Instead, you must explicitly tell a layer instance to re-cache the content, either by sending it a setNeedsDisplay or setNeedsDisplayInRect: message, or by setting its needsDisplayOnBoundsChange property to YES.

Also

drawLayer:inContext:

If defined, called by the default implementation of drawInContext:.

A: 

That delegate method only gets called when

- (void)drawInContext:(CGContextRef)ctx

is called.

Use:

....
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
[layer drawInContext:context];
[layer setNeedsDisplay];
Evan Mulawski
That's strange, because Apple docs doesn't say anything that I have to explicitly call this method. Then what's the point to have delegate? I will update my original post with excerpts from Apple docs.
Michael
+1  A: 

You should never change the delegate of layer of a UIView. From documentation of UIView layer property:

Warning: Since the view is the layer’s delegate, you should never set the view as a delegate of another CALayer object. Additionally, you should never change the delegate of this layer.

If you want to do custom drawing in a view simply override the drawRect: method.

If you do want to use layers you need to create your own:

UIView *myView = ...
CALayer *myLayer = [CALayer layer];
myLayer.delegate = self;
[myView.layer addSublayer:myLayer];

In both cases you need to call setNeedsDisplay on the view in the first case and on your custom layer in the second. You never call drawRect: or drawLayer:inContext: directly, they are called automatically when you call setNeedsDisplay.

loomer