iOS: Using UIView's 'drawRect:' vs. its layer's delegate 'drawLayer:inContext:'

How to decide which approach to use? Is there a use case for each one?

Always use drawRect:, and never use a UIView as the drawing delegate for any CALayer.

how come the delegate method is called if my instance is not defined to be the layer's delegate? and what mechanism prevents drawRect from being called if drawLayer:inContext: is called?

Every UIView instance is the drawing delegate for its backing CALayer. That's why [[self layer] setDelegate:self]; seemed to do nothing. It's redundant. The drawRect: method is effectively the drawing delegate method for the view's layer. Internally, UIView implements drawLayer:inContext: where it does some of its own stuff and then calls drawRect:. You can see it in the debugger:

drawRect: stacktrace

This is why drawRect: was never called when you implemented drawLayer:inContext:. It's also why you should never implement any of the CALayer drawing delegate methods in a custom UIView subclass. You should also never make any view the drawing delegate for another layer. That will cause all sorts of wackiness.

If you are implementing drawLayer:inContext: because you need to access the CGContextRef, you can get that from inside of your drawRect: by calling UIGraphicsGetCurrentContext().


drawRect should only be implemented when absolutely needed. The default implementation of drawRect includes a number of smart optimizations, like intelligently caching the view's rendering. Overriding it circumvents all of those optimizations. That's bad. Using the layer drawing methods effectively will almost always outperform a custom drawRect. Apple uses a UIView as the delegate for a CALayer often - in fact, every UIView is the delegate of it's layer. You can see how to customize the layer drawing inside a UIView in several Apple samples including (at this time) ZoomingPDFViewer.

While the use of drawRect is common, it's a practice that has been discouraged since at least 2002/2003, IIRC. There aren't many good reasons left to go down that path.

Advanced Performance Optimization on iPhone OS (slide 15)

Core Animation Essentials

Understanding UIKit Rendering

Technical Q&A QA1708: Improving Image Drawing Performance on iOS

View Programming Guide: Optimizing View Drawing


Here're codes of Sample ZoomingPDFViewer from Apple:

-(void)drawRect:(CGRect)r
{

    // UIView uses the existence of -drawRect: to determine if it should allow its CALayer
    // to be invalidated, which would then lead to the layer creating a backing store and
    // -drawLayer:inContext: being called.
    // By implementing an empty -drawRect: method, we allow UIKit to continue to implement
    // this logic, while doing our real drawing work inside of -drawLayer:inContext:

}

-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context
{
    ...
}