Как использовать drawRect для рисования в существующем представлении?

Я делаю приложение для GPS-трекинга. Каждый раз, когда он получает широту/долготу, он преобразует его в координаты (x,y) и вызывает drawRect для рисования линии между двумя парами (x,y).

Однако метод drawRect просто очищает все старое содержимое, прежде чем рисовать новое. Как я могу заставить drawRect рисовать что-то новое на существующем холсте? заранее спасибо

вот мой 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

мой класс рисования, подкласс 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);

}

person Kin    schedule 17.07.2011    source источник
comment
Никогда не используйте обозначение стрелки self->locationX, если вы действительно не знаете, что делаете (это почти никогда не бывает правильным). Это должно быть self.locationX, и вы должны включить @synthesize locationX; для создания аксессоров.   -  person Rob Napier    schedule 18.07.2011


Ответы (2)


UIView не имеет модели холста. Если вы хотите сохранить холст, вы должны создать CGLayer или CGBitmapContext и рисовать на нем. Затем нарисуйте это в своем представлении.

Я бы создал ivar для CGLayerRef, а затем drawRect: выглядел бы примерно так (не проверено):

- (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);
}

Всякий раз, когда вы хотите очистить свой холст, просто self.cgLayer = NULL.

setCgLayer: будет примерно таким:

- (void)setCgLayer:(CGLayerRef)aLayer {
    CGLayerRetain(aLayer);
    CGLayerRelease(cgLayer_);
    cgLayer_ = aLayer;
}
person Rob Napier    schedule 17.07.2011
comment
@Kin, обязательно оставляйте комментарии как комментарии, а не ответы. Модератор удалил ваш ответ без ответа. CGLayerRef будет переменной экземпляра (ivar) в представлении. Он должен иметь имя вроде RouteTrackView, а не routetrack. - person Rob Napier; 18.07.2011

Что именно вы подразумеваете под «старым содержанием»? Если вы хотите нарисовать линию из ваших данных GPS, вы должны каждый раз рисовать все точки в реализации drawRect.

person tomk    schedule 17.07.2011
comment
например. впервые GPS получил широту / долготу, и функция использует эти данные для рисования линии и ее отображения. Но в следующий раз, когда GPS получит новые данные, старая линия исчезнет и будет нарисована новая линия. Это не я хочу. Я хочу, чтобы старая линия существовала и рисовала новую линию. - person Kin; 17.07.2011
comment
Точно. Вы должны рисовать все линии каждый раз. Итак, вам нужно сохранить все свои координаты, например, в NSMutableArray и нарисовать содержимое всего массива im drawRect. - person tomk; 17.07.2011