Search code examples
iphonedrawingcore-animationcore-graphics

Drawing custom graphics on the iPhone: CALayer vs. CGContext


I have an application in which I'm doing some custom drawing, a bunch of lines on a gradient background, like so (ignore the text, they're just UILabels):

http://prehensile.co.uk/outgoing/Screenshot2010-06-09at12.22.32.png

At the moment, that's all done by starting a new CGContext, drawing stuff into it with CGContextDrawLinearGradient and CGContextStrokePath, then finally saving the resulting image with UIGraphicsGetImageFromCurrentImageContext. The positioning info is calculated while I'm laying out those labels, so it'd be a PITA (and duplication of effort) to calculate it all over again when the containing UIView is drawn with drawRect, so I'm drawing it ahead of time into a UIImage. All works fine, so far so good.

However, I have a sneaking suspicion that it may be more efficient to use CALayers to do this drawing. My (cursory) understanding of the difference between the two approaches is that a CALayer is more like a bunch of instructions to draw stuff, and so takes up less memory until it's actually drawn onscreen, whereas drawing everything into a UIImage ahead of time means that you've got a sodding great bitmap kicking around in memory all the time, whether it's drawn or not.

Is that a correct understanding? What is generally considered to be the best way of drawing custom images on the iPhone?


Solution

  • Pretty late answer, but maybe it will be useful.

    CA is a higher layer of abstraction than CG, so pretty much everything you do in CA will be eventually be implemented in CG, but there are a few advantages where the processing will happen at render time and save you your memory storage.

    For the paths you draw, you can use a CAShapeLayer and set the path and stroke colours when you're doing the layout. Each CAShapeLayer has it's own stroke style, so, since it looks like you're using some white lines and several thicknesses of black, each different line style would need a separate CAShapeLayer.

    For the linear gradient, you could make a 1x50 image and let a CALayer stretch that to the required width at render time. Set a CALayer's contents to the CGImageRef and whichever mode it is to stretch the contents.

    CALayers would be a clear win for memory footprint; processing time is never obvious; pre-rendered images might still win there.