Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does drawRect: work without calling [super drawrect:rect]?

I'm overriding drawRect: in one of my views and it works even without calling [super drawrect:rect]. How does that work?

- (void)drawRect:(CGRect)rect{  
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(context, kCGBlendModeDestinationOver);
    [[UIColor clearColor] setFill];
    UIRectFill(CGRectMake(0,0,100,100));
}
like image 945
wakeup Avatar asked Oct 21 '14 05:10

wakeup


2 Answers

From the documentation:

"The default implementation of this method does nothing.Subclasses that use technologies such as Core Graphics and UIKit to draw their view’s content should override this method and implement their drawing code there"

Also from the documentation..

"If you subclass UIView directly, your implementation of this method does not need to call super. However, if you are subclassing a different view class, you should call super at some point in your implementation."

Link to the documentation

I am assuming, your super class is UIView. Hence it works even if [super drawrect:rect] is not called. Because the drawRect: because UIView does nothing. So it makes no difference in this case whether or not you call [super drawrect:rect].

like image 77
Shanti K Avatar answered Oct 22 '22 11:10

Shanti K


Basically, it works because the machinery that sets up the graphics context for drawing, etc, doesn't live in the UIView implementation of -drawRect: (which is empty).

That machinery does live somewhere, of course, let's pretend in every UIView there's some internal method like this-- names of methods, functions, and properties are invented to protect the innocent:

- (void)_drawRectInternal:(CGRect)rect
{
    // Setup for drawing this view.
    _UIGraphicsContextPushTransform(self._computedTransform);

    // Call this object's implementation of draw (may be empty, or overridden).
    [self drawRect:rect];

    // draw our subviews: 
    for (UIView * subview in [self subviews]) {
        [subview _drawRectInternal:rect];
    }

    // Teardown for this view.
    _UIGraphicsContextPopTransform();
}

This is a cleaner way of building the frameworks than relying on a subclasser to do the right thing in a common override, where getting it wrong would have result in very puzzling bad behavior. (And this wouldn't really be possible at all since the draw might need a setup and a teardown step.)

like image 37
Ben Zotto Avatar answered Oct 22 '22 13:10

Ben Zotto