Search code examples
iphoneiosgraphicscore-animationcalayer

Drawing a UIImage into CALayer.contents does not render image data


I am having a wicked time trying to get an image to show up in a CALayer.contents. It seems rather straight forward but I cannot get the image to render no matter what I do. The CALayer renders fine as I can see its background color and corner radius, but the image will not load.

enter image description here

What you are seeing here is a CAGradientLayer subclass with a mask applied. The inner square is where I would like the image to show, and it is added as a sublayer of the CAGradientLayer subclass.

The code to set this up is pretty straightforward. In init:

self.imageLayer = [CALayer layer];
self.imageLayer.cornerRadius = kDefaultCornerRadius;
self.imageLayer.backgroundColor = [UIColor darkGrayColor].CGColor;
[self addSublayer:self.imageLayer];

Then later on, I set the image:

- (void)setImage:(UIImage *)image {
    self.imageLayer.contents = (id)image.CGImage;
    [self.imageLayer setNeedsDisplay];
}

Finally, within setFrame:

CGFloat imageSize = self.bounds.size.width - 2*kDefaultMargin;
[self.imageLayer setBounds:CGRectMake(0.0, 0.0, imageSize, imageSize)];
[self.imageLayer setPosition:CGPointMake(self.bounds.size.width/2.0f, kDefaultMargin + imageSize/2.0f)];
[self.imageLayer setNeedsDisplay];

Things I already know or have checked:

  1. The layer is obviously added correctly evident by it being visible.
  2. The image is added and works. [UIImage imageNamed:@"info.png"] is being used elsewhere in the code and actually shows and image. It is 16x16 at 1x and 32x32 at 2x
  3. The code is being called in the correct logical order: init, setImage:, setFrame;

What is going on here?


Solution

  • Remove this line:

    [self.imageLayer setNeedsDisplay];
    

    -setNeedsDisplay tells a layer that it needs to redraw its contents. Since you already provided the content for the layer, you don't want CA to discard that content and ask for a replacement.