Search code examples
ioscalayercagradientlayer

CAGradientLayer crashes with "exc_bad_access" in simplest possible use case


A plain UIView subclass, with ONLY the following code:

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

        CAGradientLayer* gradientLayer = [CAGradientLayer layer];
        gradientLayer.colors = [NSArray arrayWithObjects:[UIColor whiteColor], [UIColor blackColor], nil];
        gradientLayer.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], nil];

        [self.layer addSublayer:gradientLayer];

    return self;
}

Kills the runtime with EXC_BAD_ACCESS (and no, there's no Zombies, before you ask).

Also, it's NOT the CAGradientLayer getting over-released - putting multiple floating retain's on the layer has no effect.

(Incidentally, I have never seen CAGradientLayer actually work, on any project I've been on. I think it's cursed :). I wouldn't use it, except I need animated gradients, and Apple's CGGradient class only supports const arrays, which makes the animation code horrendously bug-prone)


Solution

  • The problem might be here:

    gradientLayer.colors = [NSArray arrayWithObjects:[UIColor whiteColor], [UIColor blackColor], nil];
    

    Those colors need to be the Core Graphic equivalents so this might work.

    gradientLayer.colors = [NSArray arrayWithObjects:(__bridge id)[UIColor whiteColor].CGColor, (__bridge id)[UIColor blackColor].CGColor, nil];