Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a class which is a subclass of UIView. I am able to draw stuff inside the view either by implementing the drawRect method, or by implementing drawLayer:inContext: which is a delegate method of CALayer.

I have two questions:

  1. How to decide which approach to use? Is there a use case for each one?
  2. If I implement drawLayer:inContext:, it is called (and drawRect isn't, at least as far as putting a breakpoint can tell), even if I don't assign my view as the CALayer delegate by using:

    [[self layer] setDelegate:self];

    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?

like image 809
Itamar Katz Avatar asked Feb 12 '11 16:02

Itamar Katz


1 Answers

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().

like image 71
Nathan Eror Avatar answered Oct 06 '22 00:10

Nathan Eror