UIView draw rect retain's the previous drawing and does not clear on view.transform
Asked Answered
D

2

6

I have the following code to show marker in a UIView. The marker show's well, and once we try to pinch zoom and scale the UIView using the transform the first drawing remains as it is, even after calling setNeedsDisplay.

My Custom UIView subclass has the following code

- (void)drawRect:(CGRect)rect
{
    // Drawing code
    CGFloat w=20.0f;
    CGFloat h=8.0f;


    CGContextRef context=UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextClearRect(context,self.bounds);

    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    CGContextSetLineCap(context, 2.0);


    CGMutablePathRef leftMarker=CGPathCreateMutable();
    CGPathMoveToPoint(leftMarker, NULL, 0, 0);
    CGPathAddLineToPoint(leftMarker, NULL, w, 0);
    CGPathAddLineToPoint(leftMarker,NULL, w, h);
    CGPathAddLineToPoint(leftMarker,NULL, h, h);
    CGPathAddLineToPoint(leftMarker,NULL,h, w);
    CGPathAddLineToPoint(leftMarker,NULL,0, w);
    CGPathAddLineToPoint(leftMarker,NULL, 0, 0);

    CGContextAddPath(context, leftMarker);

    CGContextDrawPath(context, kCGPathFill);
    const CGAffineTransform rightMarkerTransform=CGAffineTransformMakeRotateTranslate(DEGREES_TO_RADIANS(90),self.frame.size.width,0);

    CGPathRef rightMarker=CGPathCreateCopyByTransformingPath(path, &rightMarkerTransform);
    CGContextAddPath(context, rightMarker);
    CGContextDrawPath(context, kCGPathFill);
    const CGAffineTransform leftMarkerBottomTransform=CGAffineTransformMakeRotateTranslate(DEGREES_TO_RADIANS(270),0,self.frame.size.height);

    CGPathRef leftMarkerbottom=CGPathCreateCopyByTransformingPath(path, &leftMarkerBottomTransform);
    CGContextAddPath(context, leftMarkerbottom);
    CGContextDrawPath(context, kCGPathFill);

    const CGAffineTransform rightMarkerBottomTransform=CGAffineTransformMakeRotateTranslate(DEGREES_TO_RADIANS(180),self.frame.size.width,self.frame.size.height);

    CGPathRef rightMarkerBottom=CGPathCreateCopyByTransformingPath(path, &rightMarkerBottomTransform);
    CGContextAddPath(context, rightMarkerBottom);
    CGContextDrawPath(context, kCGPathFill);

    CGPathRelease(rightMarker);
    CGPathRelease(leftMarkerbottom);
    CGPathRelease(rightMarkerBottom);
    CGPathRelease(leftMarker);
}

The pinch zoom code is listed below

CGFloat lastScale;
-(void) handlepinchGesture:(UIPinchGestureRecognizer*)gesture{
    UIView *gestureV=gesture.view;
    CGFloat scale=gesture.scale;
    switch (gesture.state) {
        case UIGestureRecognizerStateBegan:
            if(lastScale<1.0){
            lastScale=1.0;
            }
            scale=lastScale;
            break;
        default:
            break;
    }

    if(scale<1.0){
        scale=1.0;
    }
    lastScale=scale;
    gestureV.transform=CGAffineTransformMakeScale(scale, scale);
    //Even this does not work ….[gestureV setNeedsDisplay];
    gesture.scale=scale;
}
Dong answered 18/8, 2014 at 9:40 Comment(0)
P
12

Make you sure have this set (but it should be defaulted to YES).

self.clearsContextBeforeDrawing = YES;

From Apple's Docs in UIView

When set to YES, the drawing buffer is automatically cleared to transparent black before the drawRect: method is called. This behavior ensures that there are no visual artifacts left over when the view’s contents are redrawn. 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. The default value of this property is YES.

If you set the value of this property to NO, you are responsible for ensuring the contents of the view are drawn properly in your drawRect: method. If your drawing code is already heavily optimized, setting this property is NO can improve performance, especially during scrolling when only a portion of the view might need to be redrawn.

Paulinepauling answered 18/8, 2014 at 12:49 Comment(2)
Settings the background color did it for meUnbosom
@FabienWarniez You need to make this an answer. I lost half a day trying to figure this out, this is the only thing that worked.Cornwall
U
11

You need to set the background color to something other than nil.

From DBD's answer (which is taken from the docs):

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.

You also need to make sure self.clearsContextBeforeDrawing is set to YES.

Unbosom answered 10/5, 2017 at 16:52 Comment(1)
I've spent the better part of the last week trying to figure out why drawing code that was working fine on an iPad behaved much different on tvOS and this was the reason. One stupid line from the docs...Jan

© 2022 - 2024 — McMap. All rights reserved.