将委托分配给CALayer的子图层会抛出EXC_BAD_ACCESS吗?

时间:2012-02-21 22:34:45

标签: objective-c cocoa-touch delegates drawing calayer

我正在尝试使用一系列CALayers作为一个视图的子图层,需要比平时更精细的绘图。我之前一直在使用CATiledLayer,我认为使用子图层会更容易,如果不是同样挑剔的话。我想我执行了[self.layer addSublayer:sublayer],设置了新子层的委托,然后我在drawLayer:inContext:方法中绘制了我想要的所有内容。但令我惊讶的是, 我的应用程序在addSubview: (没有IB)或调用堆栈上方(使用IB时)的某个地方崩溃。

根据文件......

CALayer reference似乎完全决定了我在做什么,但每次都会崩溃:

  

在iOS中,如果图层与UIView对象相关联,则必须将此属性设置为拥有该图层的视图。

但显然,我搞砸了。值得庆幸的是,它很容易重现。你能解释一下我应该如何使用带有委托作业的子层来接收正确的drawLayer:inContext:电话而不会崩溃吗?

重现的步骤

将此放在使用Interface Builder放在屏幕上的自定义视图的类中(或重写要称为initWithFrame:的init):

- (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);
}

如果您运行此代码,您的应用将崩溃。注意sublayer.delegate = self行。如果禁用该应用程序,您的应用程序将运行,但永远不会为该子图层调用drawLayer:inContext:方法。

我做错了什么?

1 个答案:

答案 0 :(得分:15)

这不起作用,因为UIView你是子类(我假设它是一个UIView)已经是它自己的CALayer的委托,它不能同时是多个CALayer的委托。这篇文章有更多细节:

Using CALayer Delegate