UIView draw rect preserves the previous drawing and is not cleared on view.transform

I have the following code to display a marker in a UIView. The marker shows up well, and as soon as we try to scale up and scale the UIView with a transform, the first drawing will remain as it is, even after calling setNeedsDisplay.

My custom subclass of UIView 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); } 

Below is the zoom code when clicked

 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; } 
+5
source share
2 answers

Make sure you have this set (but by default it should be equal to YES).

self.clearsContextBeforeDrawing = YES;

From Apple Docs to UIView

When set to YES, the drawing buffer is automatically flushed to transparent black before calling the drawRect: method. This behavior ensures that no visual artifacts remain when the contents of the views are redrawn. If the opaque views property is also set to YES, the backgroundColor property of the view must not be nil or a drawing error may occur. The default value of this property is YES.

If you set this property to NO, you are responsible for ensuring that the content of the view is displayed correctly in your drawRect: method. If your drawing code is already highly optimized, setting this property to NO can improve performance, especially during scrolling, when you may need to redraw only part of the image.

+9
source

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

From the DBD answer (taken from the docs):

If the opaque views 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 that self.clearsContextBeforeDrawing set to YES .

+3
source

Source: https://habr.com/ru/post/1200572/


All Articles