2

I'm doing a GPS tracking app. Every time it receives a Latitude/Longitude it converts it to (x,y) coordinates and calls drawRect to draw a line between two (x,y) pairs.

However, the drawRect method just clear all the old contents before it draw new thing. How I can make the drawRect to draw new thing on the existing canvas? Thanks in advance

here is my viewController.h

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h> 

@class routetrack;

@interface simpleDrawViewController : UIViewController <CLLocationManagerDelegate> {

    CLLocationManager *locationManager;
    IBOutlet routetrack *routeroute;

    float latOld;
    float longOld;
    float latNew;
    float longNew;
}

- (IBAction) gpsValueChanged;

@property (nonatomic,retain) CLLocationManager  *locationManager;
@property (retain,nonatomic) routetrack *routeroute;

ViewController.m

#import "simpleDrawViewController.h"
#import "routetrack.h"

@implementation simpleDrawViewController
@synthesize locationManager,btn,routeroute;

- (IBAction) gpsValueChanged{

            [routeroute setLocationX:longNew setLocationY:latNew 
             oldLocation:longOld oldLocationY:latOld ];
            [routeroute setNeedsDisplay];

}


- (void)viewDidLoad {
    [super viewDidLoad];

    if (nil == locationManager)
    locationManager = [[CLLocationManager alloc] init];

    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;  

    [locationManager startUpdatingLocation];
}



- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];    
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void) locationManager:(CLLocationManager *)manager 
         didUpdateToLocation:(CLLocation *)newLocation 
         fromLocation:(CLLocation *)oldLocation
{   
         if (oldLocation) {

            latOld=oldLocation.coordinate.latitude;
            longOld=oldLocation.coordinate.longitude;
            latNew=newLocation.coordinate.latitude;
            longNew=newLocation.coordinate.longitude;   
}

        else {
            latOld=53.3834;
            longOld=-6.5876;
            latNew=53.3835;
            longNew=-6.5877;
        }

        [self gpsValueChanged];

}



- (void) locationManager:(CLLocationManager *)manager didFailwithError:
(NSError *)error
{
    if([error code] == kCLErrorDenied)
        [locationManager stopUpdatingLocation];

    NSLog(@"location manger failed");
}




- (void)dealloc {
    [locationManager release];
    [super dealloc];
}

@end

my drawing class, a subclass of UIView

#import "routetrack.h"


@implementation routetrack



- (void) setLocationX:(float) loX setLocationY:(float) loY 
         oldLocation:(float) oldX oldLocationY:(float) oldY {


    self->locationX = loX;
    self->locationY = loY;
    self->oldLoX = oldX;
    self->oldLoY = oldY;

    scaleX= 36365.484375;
    scaleY= 99988.593750;
    maxLat= 53.3834;
    maxLog= -6.5976;

    drawX = locationX;
    drawY = locationY;

    tempX=(maxLog - drawX) * scaleX;
    tempY=(maxLat   - drawY) * scaleY;

    lastX = (int) tempX;
    lastY = (int) tempY;

    drawX = oldLoX;
    drawY = oldLoY;

    tempX=(maxLog - drawX) * scaleX;
    tempY=(maxLat   - drawY) * scaleY;

    startX = (int) tempX;
    startY = (int) tempY;


}

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
    }
    return self;

}


- (void)drawRect:(CGRect)rect {

        int firstPointX = self->startX; 
    int firstPointY = self->startY;
    int lastPointX = self->lastX;
    int lastPointY = self->lastY;

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
    CGContextSetLineWidth(context, 2.0);

    CGContextMoveToPoint(context, firstPointX, firstPointY);

    CGContextAddLineToPoint(context, lastPointX , lastPointY);

    CGContextStrokePath(context);

}
yuji
  • 16,695
  • 4
  • 63
  • 64
Kin
  • 21
  • 1
  • 3
  • Never use the arrow notation `self->locationX` unless you really know what you're doing (this is almost never correct). This should be `self.locationX` and you should include `@synthesize locationX;` to create the accessors. – Rob Napier Jul 18 '11 at 13:38

2 Answers2

4

UIView does not have a canvas model. If you want to keep a canvas, you should create a CGLayer or a CGBitmapContext and draw onto that. Then draw that in your view.

I would create an ivar for a CGLayerRef, and then drawRect: would look something like this (untested):

- (void)drawRect:(CGRect)rect {
    if (self.cgLayer == NULL) {
        CGLayerRef layer = CGLayerCreateWithContext(UIGraphicsContextGetCurrent(), self.bounds, NULL);
        self.cgLayer = layer;
        CGLayerRelease(layer);
    }

    ... various Core Graphics calls with self.cgLayer as the context ...

    CGContextDrawLayerInRect(UIGraphicsContextGetCurrent(), self.bounds, self.cgLayer);
}

Whenever you wanted to clear your canvas, just self.cgLayer = NULL.

setCgLayer: would be something like this:

- (void)setCgLayer:(CGLayerRef)aLayer {
    CGLayerRetain(aLayer);
    CGLayerRelease(cgLayer_);
    cgLayer_ = aLayer;
}
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • @Kin, make sure to post comments as comments, not answers. The moderator has removed your non-answer answer. The CGLayerRef would be an instance variable (ivar) on the view. It should have a name like RouteTrackView, not "routetrack". – Rob Napier Jul 18 '11 at 13:35
1

What exactly to you mean by "old contents"? If you want to draw a line from your GPS data, you have to draw all points every time in the implementation of drawRect.

tomk
  • 1,356
  • 1
  • 9
  • 14
  • eg. first time GPS got lat/long and the function use that data to draw a line and display it. But next time GPS got new data, the old line is disappear and a new line is drawn. That's not I want. I want to the old line exist and draw a new line. – Kin Jul 17 '11 at 16:27
  • Exactly. You have do draw all lines, every time. So you need to store all your coordinates in an NSMutableArray for example and draw the contents of the whole array im drawRect. – tomk Jul 17 '11 at 16:44