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

epo*_*gee 7 cocoa-touch drawing delegates objective-c calayer

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

根据文件......

CALayer的参考似乎决定了我在做什么,但它崩溃每次:

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

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

重现步骤

将它放在使用Interface Builder放在屏幕上的自定义视图的类中(或重写要调用的init 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);
}
Run Code Online (Sandbox Code Playgroud)

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

我究竟做错了什么?

Tar*_*ark 15

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

使用CALayer委托