views:

43

answers:

1

Hi all. I've just found a strange issue with my sub classed mkannotationview.

When I add the first 5 markers, they all work perfectly. In the mkannotationview sub class, I NSLog a message which I see 5 times. However, when I remove ALL the markers and redraw them - using all the same methods, I see the NSLog only once.

It's like the map is reusing existing annotationviews? Is there a way to force it to use new ones each time?

[UPDATE with code]

So the reason I cannot reuse (and this may or may not be the problem) is that I am creating unique markers with a label. The label on the marker contains a reference to the individual marker (consider it like a product ID)

So... in ProductPlot.h

@interface ProductPlot : NSObject <MKAnnotation> {
    NSString *productID;
    float latitude;
    float longitude;
}
@property (nonatomic, copy) NSString *productID;

and ProductPlot.m

@implementation ProductPlot
@synthesize productID;

- (CLLocationCoordinate2D)coordinate {
    CLLocationCoordinate2D coord = {self.latitude, self.longitude};
    return coord;
}

- (NSString *) productID {
    return productID;
}

then I have the annotation view sub classed as ProductPlotView.h

@interface ProductPlotView : MKAnnotationView {
ProductPlot *product;
}

and in ProductPlotView.m

@implementation ProductPlotView

- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
    if(self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {

        product = (ProductPlot *)annotation;
        UILabel *plate2 = [[[UILabel alloc] init] autorelease];
        plate2.text = product.productID;
        plate2.frame = CGRectMake(35, 4, 100, 30);
        plate2.backgroundColor = [UIColor clearColor]; //]clearColor];
        [plate2 setFont: [UIFont fontWithName: @"myFont" size: plate2.font.pointSize]];

        [self addSubview:plate2];
    }
    self.frame = CGRectMake(0,0,133,40);

    return self;
}

So then in my code, I plot the points using

- (void)plotPoint: (int) y latitude: (double) lat longitude: (double) lng productID: (NSString *) pID {

    ProductPlot *newAnnotation = [[ProductPlot alloc] init];
    newAnnotation.latitude = lat;
    newAnnotation.longitude = lng;
    newAnnotation.productID = pID;
    [mapView addAnnotation:newAnnotation];

    [newAnnotation release];

}

I also have the code to handle the annotations.

- (MKAnnotationView *)mapView:(MKMapView *)lmapView viewForAnnotation:(id <MKAnnotation>)annotation {



    ProductPlotView *eventView = (ProductPlotView *)[lmapView
                                    dequeueReusableAnnotationViewWithIdentifier:@"eventview"];
    if(eventView == nil) {
        eventView = [[[VehicleViewInfo alloc] initWithAnnotation:annotation
                                                     reuseIdentifier:@"eventview"]
                     autorelease];
    }

    eventView.annotation = annotation;
    return eventView;
}

So... the above will take the productID and place it on a label which is the map marker. This seems to work perfectly on the FIRST plot instance, but if I remove the markers (using [mapView removeAnnotations:mapView.annotations];) then call this function again, it draws the points OK, but the product IDs are not correct. It appears to draw them at random.

NOTE: the code above has had a few parts removed, so there may be typos

Thanks for any info.

A: 

To answer my own question, I added MKAnnotationView* annotationView = nil; to the top of my - (MKAnnotationView *)mapView:(MKMapView *)lmapView viewForAnnotation:(id <MKAnnotation>)annotation code.

Now it seems to be working perfectly. I'd still be keen to see if others think that this is the correct way to do this?

Matt Facer
Reuse queues are the best practice for a reason. You can hack it like so but you are not following the standard design pattern. You'll be fine with a small set of annotations but consider doing things the reuse way.
Nick
Yes I agree totally... I want to reuse, believe me! There will only ever be around 10 markers on the screen at once, but even then I'd rather go for speed. I just need to find a way to delete the label on the marker - or just reset the text within. I'm probably missing something... thanks.
Matt Facer
basically each marker needs to be unique... so if it's reused - I need to then just override the label. I'll have a think and repost the solution (if indeed I find one!)
Matt Facer
You can just override `setAnnotation:(id<MKAnnotation>)annotation` in your `MKAnnotationView` subclass (I believe you called it `VehicleViewInfo`). When it gets called, you need to update the label. Make sense?
Itay