简体   繁体   中英

MKMapview annotation dynamic pin image changes after zooming

I am working on a little project that shows 7 different types of annotations on the map. My annotations are taken from a url result in array and I parse it using JSON. I have lots of annotations and everything seems to look good once the map loads. After zooming in and zooming out, the the pin images changes for some reason to the wrong pin image (a specific image, no clue why).

I am sure I am missing something here...may you please help :) ?

Here's one part of my code, let me know if you need anymore of it:

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

static NSString *identifier;

if(_mapView.tag==1){identifier = @"TurbulencePin";}
if(_mapView.tag==2){identifier = @"IcingPin";}
if(_mapView.tag==3){identifier = @"WindsPin";}
if(_mapView.tag==4){identifier = @"TemperaturePin";}
if(_mapView.tag==5){identifier = @"CloudsPin";}
if(_mapView.tag==6){identifier = @"VisibilityPin";}
if(_mapView.tag==7){identifier = @"MultiplePin";}


if ([annotation isKindOfClass:[MKUserLocation class]])
    return nil;

if ([annotation isKindOfClass:[Annotation class]]) {

    CustomAnnotationView* annotationView = (CustomAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    annotationView = nil;

    if (annotationView == nil) {

        annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
        annotationView.enabled = YES;
        annotationView.canShowCallout = YES;


        UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"%@.png",identifier]];
        annotationView.image = img;

    }
else
    {

        annotationView.annotation = annotation;

    }


    return annotationView;

}
return nil;

}

Update:

Based upon feedback of others, I've modified the code for the image setting to be as follows:

 Annotation *myCustomAnn = (Annotation *)annotation;
 NSString *imgName = myCustomAnn.imageName;
 UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"%@Pin.png",imgName]];
 annotationView.image = img;

 return annotationView;

Plus, I removed the annotationView = nil;

However, I cannot set the image name in the annotation.m as a hardcoded value because I need to display a different pin image for each annotation. I'm sure that there is an explanation but the only value that I can get from the annotation.m under the mapView:viewForAnnotation: is the annotation coordinates ( myCustomAnn.coordinate.latitude and myCustomAnn.coordinate.longitude) , I have no clue how to get other properties from the annotation.m

The other properties, such as title, imgname etc comes back as null

The main problem is that the code in viewForAnnotation is relying on the outside variable _mapView.tag to determine the annotation view.

It is unsafe to assume when and how frequently the viewForAnnotation delegate method will be called by the map.

If an annotation's view depends on certain values, it is generally best to embed those values directly in the annotation object itself. This way, in the viewForAnnotation delegate method, you can reference those annotation-specific values through the annotation parameter that is passed to the method. Those annotation-specific values should be set when creating the annotation (before calling addAnnotation ).

For some more details and examples, see:

A separate issue is the code is setting annotationView to nil after calling dequeueReusableAnnotationViewWithIdentifier which defeats the dequeue.


At least in viewForAnnotation , the corrected code where it handles the Annotation class might look like this (not the whole method -- just the part inside the second if ):

static NSString *identifier = @"ann";

CustomAnnotationView* annotationView = (CustomAnnotationView*)[mapView 
    dequeueReusableAnnotationViewWithIdentifier:identifier];

//annotationView = nil;  // <-- remove this line

if (annotationView == nil) 
{
    annotationView = [[CustomAnnotationView alloc] 
                         initWithAnnotation:annotation 
                         reuseIdentifier:identifier];
    annotationView.enabled = YES;
    annotationView.canShowCallout = YES;
}
else
{
    annotationView.annotation = annotation;
}

//MOVE the setting of the image to AFTER the dequeue/create 
//because the image property of the annotation view 
//is based on the annotation and we can update image in one place
//after both the dequeue and create are done...

//Get the image name from the annotation ITSELF 
//from a custom property (that you add/set)
Annotation *myCustomAnn = (Annotation *)annotation;

NSString *imgName = myCustomAnn.imageName;  
//imageName is the custom property you added/set

UIImage *img = [UIImage imageNamed:
                   [NSString stringWithFormat:@"%@.png",imgName]];

annotationView.image = img;

return annotationView;

SOLVED by Rob

The problem was, that I could not retrive the annotation properties which I set at my VC. The reason was that I used the [_mapView addAnnotation:ann]; command, before I set all the annotation's properties. That said, by moving this line to the end part of the annotation initial properties setup, solved the problem.

Thank you all and big thanks to Rob! I'm up to my next challenge.

One issue is that the viewForAnnotation is determining the correct image to show based upon a class instance variable. Generally the identifier for the annotation's image would be a property of the custom annotation itself, not some external instance variable.

On top of that, it appeared that the annotation was being added to the map before all of the annotation's properties were being set. One should defer the addAnnotation until all of the annotation's properties are set.

Alternatively, you can add the annotations to a NSMutableArray , tweak them as you see fit, and only add the annotations at the very end using the addAnnotations (note the s), passing it the array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM