title: iOS Animate Dashed Rectangle Border
body: <p>I have a UIImageView displaying an image. I want to "highlight" a portion of the image by drawing a rounded rectangle outline. I would like to have the outline drawn with a thick, dashed line that "animates" by continually varying where the "beginning" of the line starts.</p>
  
  <p>I thought about drawing a circle that had the look I want and then simply animating it, but I really need a rectangular solution, so that's out.</p>
  
  <p>Background:</p>
  
  <p>I'm drawing the rounded rectangle border by calculating 8 points and drawing 4 straight lines and 4 curves. (Maybe this can be easier, but it's not the broken part!)</p>
  
  <p>My thinking is that I'll use an "offset" variable that starts at the top-left of the rounded rectangle, where the top-left curve meets the top straight piece. Then, I will increment this "offset" across the top of the rounded rectangle until it reaches the top-right curve, whereupon I will "reset" the "offset" variable to its original value.</p>
  
  <p>This is working pretty much as I'd like, until the "reset" occurs. At this point, the animation is jerky (kind of expected), but it also appears to travel in reverse for a small portion of the time, before resuming "forward" motion. Finally, at the beginning/end of my dashed line, I get an extra long segment on the dashed line. I know they can't all be equal-length (can they? how to calculate?), but how can I make 2 shorter segments rather than 1 longer segment?</p>
  
  <p>Anybody have an idea of what I can do to get a smooth "marching ants" kind of look? Any other ideas on a good way to (using animation) call the user's eye to a particular area of the screen? (It needs to surround a particular area without obscuring it.)</p>
  
  <p>Current code:</p>
  
  <pre><code>- (void)drawRect:(CGRect)rect
  {
      CGContextRef context = UIGraphicsGetCurrentContext();
      CGContextClearRect(context, rect);
  
      // Rounded corner will be 10% of average side length (i.e., (w + h) / 2)
      float averageSide = ([self HighlightRect].size.width + [self HighlightRect].size.height) / 2.0;
      float roundSize = averageSide * 0.10;
  
      // offset is a static, class variable
      offset += roundSize / 4.0;
      if ([WhereIAmView offset] &lt; roundSize) {
          offset = roundSize;
      }
      if ([WhereIAmView offset] &gt; ([self HighlightRect].size.width - roundSize)) {
          offset = roundSize;
      }
  
      // Set the "main" color of the rounded rectangle
      UIColor *lineColor = [UIColor colorWithRed:027.0/255.0 green:050.0/255.0 blue:224.0/255.0 alpha:1.0];
      CGContextSetStrokeColorWithColor(context, [lineColor CGColor]);
      CGContextSetLineWidth(context, 16.0);
      CGFloat pattern[] = {25.0, 5.0};
      CGContextSetLineDash(context, offset, pattern, 2);
  
      CGRect rRect = [self HighlightRect];
      // The top left corner
      CGPoint topLeft = CGPointMake(rRect.origin.x, rRect.origin.y);
      // The top right corner
      CGPoint topRight = CGPointMake(rRect.origin.x + rRect.size.width, rRect.origin.y);
      // The bottom right corner
      CGPoint bottomRight = CGPointMake(rRect.origin.x + rRect.size.width, rRect.origin.y + rRect.size.height);
      // The bottom left corner
      CGPoint bottomLeft = CGPointMake(rRect.origin.x, rRect.origin.y +     rRect.size.height);
  
      // The two points across the top of the rounded rectangle (left to right)
      CGPoint point1 = CGPointMake(rRect.origin.x + roundSize, rRect.origin.y);
      CGPoint point2 = CGPointMake(rRect.origin.x + rRect.size.width - roundSize, rRect.origin.y);
      // The two points along the right of the rounded rectangle (top to bottom)
      CGPoint point3 = CGPointMake(rRect.origin.x + rRect.size.width, rRect.origin.y + roundSize);
      CGPoint point4 = CGPointMake(rRect.origin.x + rRect.size.width, rRect.origin.y + rRect.size.height - roundSize);
      // The two points along the bottom of the rounded rectangle (right to left)
      CGPoint point5 = CGPointMake(rRect.origin.x + rRect.size.width - roundSize, rRect.origin.y + rRect.size.height);
      CGPoint point6 = CGPointMake(rRect.origin.x + roundSize, rRect.origin.y + rRect.size.height);
      // The two points along the left of the rounded rectangle (bottom to top)
      CGPoint point7 = CGPointMake(rRect.origin.x, rRect.origin.y + rRect.size.height - roundSize);
      CGPoint point8 = CGPointMake(rRect.origin.x, rRect.origin.y + roundSize);
  
      // Move to point 1
      CGContextMoveToPoint(context, point1.x, point1.y);
      // Add line to point 2 (this is the straight portion across the top)
      CGContextAddLineToPoint(context, point2.x, point2.y);
      // Add curve to point 3 (this is the rounded portion in top right)
      CGContextAddArcToPoint(context, topRight.x, topRight.y, point3.x, point3.y, roundSize);
      // Add line to point 4 (this is the straight portion across the right)
      CGContextAddLineToPoint(context, point4.x, point4.y);
      // Add curve to point 5 (this is the rounded portion in bottom right)
      CGContextAddArcToPoint(context, bottomRight.x, bottomRight.y, point5.x, point5.y, roundSize);
      // Add line to point 6 (this is the straight portion across the bottom)
      CGContextAddLineToPoint(context, point6.x, point6.y);
      // Add curve to point 7 (this is the rounded portion in bottom left)
      CGContextAddArcToPoint(context, bottomLeft.x, bottomLeft.y, point7.x, point7.y, roundSize);
      // Add line to point 8 (this is the straight portion across the left)
      CGContextAddLineToPoint(context, point8.x, point8.y);
      // Add curve to point 1 (this is the rounded portion in top left)
      CGContextAddArcToPoint(context, topLeft.x, topLeft.y, point1.x, point1.y, roundSize);
  
      // Stroke the path
      CGContextStrokePath(context);
  
  }
  </code></pre>
  
  <p>bump
  bump bump</p>