objective-c - 将委托(delegate)分配给 CALayer 的子层会抛出 EXC_BAD_ACCESS?

标签 objective-c cocoa-touch delegates drawing calayer

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

根据文档...

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

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

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

重现步骤

将其放入使用 Interface Builder 显示在屏幕上的自定义 View 的类中(或将初始化重写为 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);
}

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

我做错了什么?

最佳答案

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

Using CALayer Delegate

关于objective-c - 将委托(delegate)分配给 CALayer 的子层会抛出 EXC_BAD_ACCESS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9386397/

相关文章:

ios - 如何为 URLSessionDataTask 分配委托(delegate)?

ios - 在 iOS 中聚类 Google map 标记

ios - 在 UIImagePickerController 取消按钮不显示?

ios - 是否可以合并/交叉两个 UIView 而不是让它们重叠?

objective-c - 使用 Core Data 生成的访问器的问题

c# - 如何像在 C# 中一样在 Java 中使用委托(delegate)?

ios - 弱委托(delegate)和类协议(protocol)

ios - UIView animateWithDuration 忽略持续时间

objective-c - 将填充更改为已绘制的 NSBezierPath

objective-c - NSSet 和 NSCountedSet,什么时候用最好?