Question

I want to draw a simple line on the iPhone by touching and dragging across the screen. I managed to do that by subclassing UIView and change the default drawRect: method. At the same time in my viewcontroller I detect the touch event and call the [myView setNeedsDisplay] when necessary. The problem is that when I try to draw the second line the previous line disappears. Is there a way to keep the previous line on the screen?

Any input will be very much appreciated.

Was it helpful?

Solution

If you use drawRect: to draw, then you need to draw the whole area. So you need to store not only the data for the latest part but everything.

As an alternative, you might draw directly into a bitmap, or generate dynamically subviews for your lines (makes only sense for very limited drawing (i.e. some few vector-based stuff).

OTHER TIPS

The usual method is to use CGBitmapContextCreate(). Create it in -init/-init-WithFrame:/etc and call CGContextRelease() in -dealloc. I'm not sure how you handle the 2x scale of the "retina display" with CGBitmapContextCreate().

(UIGraphicsBeginImageContext() is easier, but it might not be safe to do UIGraphicsBeginImageContext(); myContext = CFRetain(UIGraphicsGetCurrentContext()); UIGraphicsEndImageContext();.)

Then do something like

#import <QuartzCore/CALayer.h>

-(void)displayLayer:(CALayer*)layer
{
  UIGraphicsPushContext(mycontext);
  ... Update the bitmap context by drawing a line...
  UIGraphicsPopContext();
  CGImageRef cgImage = CGBitmapContextCreateImage(mycontext);
  layer.contents = (id)cgImage;
  CFRelease(cgImage);
}

I've used -displayLayer: (a CALayer delegate function; a UIView is its layer's delegate) instead of -drawRect: for efficiency: if you use -drawRect:, CALayer creates a second context (and thus a second copy of the bitmap).


Alternatively, you might have luck with CGLayer. I've never seen a reason to use it instead of a bitmap context; it might be more efficient in some cases.


Alternatively, you might get away with setting self.clearsContextBeforeDrawing = NO, but this is very likely to break. UIKit (or, more accurately, CoreAnimation) expects you to draw the whole view contained in the clip rect (that's the "rect" argument of -drawRect:; it's not guaranteed to be the bounds). If your view goes offscreen, CoreAnimation might decide that it wants the memory back. Or CoreAnimation might only draw the part of the view that's on-screen. Or CoreAnimation might do double-buffered drawing, causing your view to appear to flip between two states.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top