5

Background: I am trying to create a really simple iPhone app that will allow the user to draw multiple straight lines on the screen with their finger.

I'm using these two methods in my UIViewController to capture the coordinates of each line's endpoints.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

Question: I would like the line to show up as soon as touchesEnded has fired and then keep drawing more lines on the screen. How do I do this? I don't necessarily need the code, but I need help with the big picture idea of how to put it together. Also, I'm not a huge fan of xibs and like to do things all programmatically if that affects the answer.

What I've Tried: I've tried using Quartz 2d but it seems in order to use that, you have to do your drawing in the drawRect method of a separate subclassed view. So I would have to create a new view for each line? and then my coordinates would be messed up b/c I'd have to translate the touches positions from the UIViewController to the view.

I've also tried with OpenGL, which I've had a bit more success with (using the GLPaint sample as a template) but OpenGL seems like overkill for just drawing some straight lines on the screen.

Trevor
  • 4,620
  • 2
  • 28
  • 37
  • Indeed OpenGL is overkill for this, and you don't wanna mess with it unless you really need to. +1 for such an easy to read question, if only others would do the same... – Pochi Mar 19 '12 at 05:03

3 Answers3

3

You don't need multiple views, and you don't need OpenGL.

Make a subclass of UIView -- call it CanvasView.

Make an object to represent "a line" in your canvas -- it would be a subclass of NSObject with CGPoint properties for start and end.

CanvasView should keep an array of the lines that are in the canvas.

In -[CanvasView drawRect:], loop through the lines in the array, and draw each one.

In -[CanvasView touchesBegan:withEvent:], stash the start point in an instance variable. In -[CanvasView touchesEnded:withEvent:], make a new line with the start and end points, and add it to your array of lines. Call [self setNeedsDisplay] to cause the view to be redrawn.

Kurt Revis
  • 27,695
  • 5
  • 68
  • 74
  • wouldnt this aproach get slow if the user has ALOT of lines? wouldnt using the painters aproach of quartz be more efficient? – Pochi Mar 19 '12 at 05:02
  • 1
    This is using the "painters approach of quartz", since it's using Quartz to draw. And yes, depending on how exactly a "line" is drawn, it will get slow after a few hundred or thousand lines. This is just a basic outline of the approach, and it can certainly be optimized further. – Kurt Revis Mar 19 '12 at 05:08
2

U mentioned that you just need big picture of the idea..

So here it is..

Take a view, subclass of UIView. Capture touches events and then draw it in drawRect: method..

This is all what @kurtRevis mentioned in his answer.

Now to avoid slowing down of drawing, keep an offline image that keeps updated screen view and then just go on adding lines over that. So you wont get slowing down performance when there is big array of lines to be drawn.

Hope u are getting me.

DivineDesert
  • 6,924
  • 1
  • 29
  • 61
-1

As far as i know you can also use Core Graphics to draw a line, and from your question you don't need to create views for every single line, instead your single view graphics context will be a drawing sheet for all the drawing, and you almost nearer to the solution. Just by taking the touch coordinate you can draw the lines on the view.
CGPoint previousPoint;//This must have the global scope, it will be used in all the touch events

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{       
   UITouch *touch = [touches anyObject];
   previousPoint = [touch locationInView:self]; // take the starting touch point;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
   CGPoint currentPoint;
   UITouch *touch = [touches anyObject];   
   currentPoint = [touch locationInView:self]; 
   CGContextRef context = UIGraphicsGetCurrentContext();
   CGContextSetLineWidth(context, 2.0);
   CGContextMoveToPoint(context, previousPoint.x,previousPoint.y);
   CGContextAddLineToPoint(context, currentPoint.x,currentPoint.y);
   CGContextStrokePath(bluecontext);

}

Hope this helps you, Let me know any issue....

iDroid
  • 1,140
  • 1
  • 13
  • 30
  • This will not work, as written. You cannot draw to a view in the middle of `-touchesMoved:withEvent:`. If `UIGraphicsGetCurrentContext()` returns anything useful, it will only be by coincidence. Besides, you aren't even stroking the path, you're just adding to the current CG path. – Kurt Revis Mar 19 '12 at 07:32