UIView without backgroundColor not clearing drawing context

Originator:tobias.klonk
Number:rdar://8165730 Date Originated:2010/07/07
Status:Resolved Resolved:2010/07/30
Product:iPhone SDK Product Version:3.1.3/3.2
Classification:Bug Reproducible:always
 
Summary:

A UIView Subclass without backgroundColor, that is an instance with backgroundColor set to nil, doesn't clear its drawing context correctly, before calling drawRect:
There is pixelData from earlier call to drawRect: left in the context.

Steps to Reproduce:

Use the attached Xcode project or create a window based app.

In the appDelegate instanciate the view and add the view to the window.

Implement the view like this:

@implementation view

- (void)drawRect:(CGRect)rect {
    static int nDrawrectCalls = 0;
    CGContextRef context = UIGraphicsGetCurrentContext();
	//CGContextClearRect(context, rect);
    CGContextSetLineWidth(context, 1.0);
    CGContextSetStrokeColorWithColor(context, (nDrawrectCalls%5==0?[UIColor redColor]:[UIColor greenColor]).CGColor);
    CGContextMoveToPoint(context, 10, 30+10*nDrawrectCalls);
    CGContextAddLineToPoint(context, 300, 30+10*nDrawrectCalls);
    CGContextStrokePath(context);
    nDrawrectCalls++;
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    [self setNeedsDisplay];
}

Expected Results:

You should see a line green line. On tap the line steps 10.0 point down. Every 5th tap the line turns red.

Actual Results:

After the nth tap, you can see the expected line plus the lines from tap n-2, n-4, n-6, etc.

Regression:

After setting any backgroundColor on the view, the bug doesn't occur.
After adding a call to CGContextClearRect() inside drawRect:, the bug doesn't occur.

Notes:

Might be that context clearing is taking the backgroundColor into account, but is not prepared or does not correctly handle a value of nil.

------------------------
28-Jul-2010 11:42 PM Patrick Collins :
Engineering has determined that this issue behaves as intended based on the following information:

Please see UIView.clearsContextBeforeDrawing property. It depends on how you setup your view. A view with a -drawRect: but marked opaque does not clear the context.

------------------------
That's right. Here the parts of the documentation in question.

Property clearsContextBeforeDrawing:

The default value of this property is YES. When set to YES, the current graphics context buffer in the drawRect: method is automatically cleared to transparent black before drawRect: is invoked. If the view’s opaque property is also set to YES, the backgroundColor property of the view must not be nil or drawing errors may occur.

If the value of this property is NO, it is the view’s responsibility to completely fill its content. Drawing performance can be improved if this property is NO—for example, when scrolling.

Property opaque:

YES if it is opaque; otherwise, NO. If opaque, the drawing operation assumes that the view fills its bounds and can draw more efficiently. The results are unpredictable if opaque and the view doesn’t fill its bounds. Set this property to NO if the view is fully or partially transparent. The default value is YES.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!