Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning a delegate to a CALayer's sublayer throws EXC_BAD_ACCESS?

I'm trying to use a series of CALayers as sublayers to a view that needs a little more fine grained drawing than usual. I've been using CATiledLayer before, and I thought using sublayers would be easier, if not equally finicky. I figured I perform a [self.layer addSublayer:sublayer], set the delegate of that new sublayer and then I draw all I want in the drawLayer:inContext: method. But to my great surprise, my app crashes on addSubview: (without IB) or somewhere higher up the call stack (when using IB).

According to the docs ...

The CALayer reference seems to dictate exactly what I'm doing, yet it crashes every time:

In iOS, if the layer is associated with a UIView object, this property must be set to the view that owns the layer.

But obviously, I'm screwing something up. Thankfully, it's easily reproducible. Can you explain to me how I should be using sublayers with delegate assignments to receive the right drawLayer:inContext: calls without crashing?

Steps to reproduce

Put this in the class of a custom view put on screen with Interface Builder (or rewrite the init to be called initWithFrame:):

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];

    if (self) {
        CALayer *sublayer = [CALayer layer];
        sublayer.frame = self.layer.bounds;

        // Disable or enable this next line to 
        // resolve or trigger an EXC_BAD_ACCESS crash.
        // 
        sublayer.delegate = self;

        [self.layer addSublayer:sublayer];
        [self.layer setNeedsDisplay];
    }

    return self;
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    CGContextSetFillColorWithColor(ctx, [[UIColor greenColor] CGColor]);
    CGContextFillRect(ctx, self.bounds);
}

If you run this code, your app will crash. Mind the sublayer.delegate = self line. If you disable that one, your app will run, but the drawLayer:inContext: method is never called for that sublayer.

What am I doing wrong?

like image 302
epologee Avatar asked Feb 21 '12 22:02

epologee


1 Answers

This does not work because the UIView you are subclassing (I assume it is a UIView) already is the delegate of its own CALayer, it cannot be the delegate of more than one CALayer at once. This post has some more details:

Using CALayer Delegate

like image 164
Tark Avatar answered Nov 13 '22 00:11

Tark