title: Drawing incrementally in a UIView (iPhone)
body: <p>As far as I have understood so far, every time I draw something in the drawRect: of a UIView, the whole context is erased and then redrawn.</p>
  
  <p>So I have to do something like this to draw a series of dots:</p>
  
  <p><strong>Method A: drawing everything on every call</strong></p>
  
  <pre><code>- (void)drawRect:(CGRect)rect { 
  
      CGContextRef context = UIGraphicsGetCurrentContext();
  
      CGContextDrawImage(context, self.bounds, maskRef);      //draw the mask
      CGContextClipToMask(context, self.bounds, maskRef);     //respect alpha mask
      CGContextSetBlendMode(context, kCGBlendModeColorBurn);  //set blending mode
  
      for (Drop *drop in myPoints) {
          CGContextAddEllipseInRect(context, CGRectMake(drop.point.x - drop.size/2, drop.point.y - drop.size/2, drop.size, drop.size));
      }
  
      CGContextSetRGBFillColor(context, 0.5, 0.0, 0.0, 0.8);
      CGContextFillPath(context);
  }
  </code></pre>
  
  <p>Which means, I have to store all my Dots (that's fine) and re-draw them all, one by one, every time I want to add a new one. Unfortunately this gives my terrible performance and I am sure there is some other way of doing this, more efficiently.</p>
  
  <p>EDIT: Using MrMage's code I did the following, which unfortunately is just as slow and the color blending doesn't work. Any other method I could try?</p>
  
  <p><strong>Method B: saving the previous draws in a UIImage and only drawing the new stuff and this image</strong></p>
  
  <pre><code>- (void)drawRect:(CGRect)rect
  {
      //draw on top of the previous stuff
      UIGraphicsBeginImageContext(self.frame.size);
      CGContextRef ctx = UIGraphicsGetCurrentContext(); // ctx is now the image's context
      [cachedImage drawAtPoint:CGPointZero];
      if ([myPoints count] &gt; 0)
      {
          Drop *drop = [myPoints objectAtIndex:[myPoints count]-1];
          CGContextClipToMask(ctx, self.bounds, maskRef);         //respect alpha mask
          CGContextAddEllipseInRect(ctx, CGRectMake(drop.point.x - drop.dropSize/2, drop.point.y - drop.dropSize/2, drop.dropSize, drop.dropSize));
          CGContextSetRGBFillColor(ctx, 0.5, 0.0, 0.0, 1.0);
          CGContextFillPath(ctx);
      }
      [cachedImage release];
      cachedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
      UIGraphicsEndImageContext();
  
      //draw on the current context   
      CGContextRef context = UIGraphicsGetCurrentContext();
      CGContextDrawImage(context, self.bounds, maskRef);          //draw the mask
      CGContextSetBlendMode(context, kCGBlendModeColorBurn);      //set blending mode
      [cachedImage drawAtPoint:CGPointZero];                      //draw the cached image
  }
  </code></pre>
  
  <p>EDIT:
  After all I combined one of the methods mention below with redrawing only in the new rect. The result is:
  <strong>FAST METHOD:</strong></p>
  
  <pre><code>- (void)addDotAt:(CGPoint)point
  {
      if ([myPoints count] &lt; kMaxPoints) {
          Drop *drop = [[[Drop alloc] init] autorelease];
          drop.point = point;
          [myPoints addObject:drop];
          [self setNeedsDisplayInRect:CGRectMake(drop.point.x - drop.dropSize/2, drop.point.y - drop.dropSize/2, drop.dropSize, drop.dropSize)];      //redraw
      }
  }
  
  - (void)drawRect:(CGRect)rect
  {
      CGContextRef context = UIGraphicsGetCurrentContext();
  
      CGContextDrawImage(context, self.bounds, maskRef);                                              //draw the mask
      CGContextClipToMask(context, self.bounds, maskRef);                                             //respect alpha mask
      CGContextSetBlendMode(context, kCGBlendModeColorBurn);                                          //set blending mode
  
      if ([myPoints count] &gt; 0)
      {
          Drop *drop = [myPoints objectAtIndex:[myPoints count]-1];
          CGPathAddEllipseInRect (dotsPath, NULL, CGRectMake(drop.point.x - drop.dropSize/2, drop.point.y - drop.dropSize/2, drop.dropSize, drop.dropSize));
      }
      CGContextAddPath(context, dotsPath);
  
      CGContextSetRGBFillColor(context, 0.5, 0.0, 0.0, 1.0);
      CGContextFillPath(context);
  }
  </code></pre>
  
  <p>Thanks everyone!</p>