MKAnnotationView fault when zoom in/out changed th

2019-02-26 04:22发布

问题:

I have used annotation map and used more than one image for the pins but whenever I zoom in or zoom out, it changes all the pins to one image.

I get the locations from a web service and to recognise them, I used a string (CustAttr) as "T" or "P".

The problem is the last call from a web service makes the CustAttr = T and when I zoom in or zoom out, it calls the mapView viewForAnnotation method and draws them all as T and all the P pins are changed.

Here is the code for the method :

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

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

}
static NSString* AnnotationIndentifer = @"AnnotationIdentifier";



if ([custAttr isEqualToString:@"T"]) // ATMs
{
    MKAnnotationView* pinView;
    pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIndentifer];

    MapAnnotation* mapAnnotation = annotation;
    pinView.canShowCallout = YES;

    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
    pinView.rightCalloutAccessoryView = rightButton;

    if (mapAnnotation.isClosest) {
        pinView.image = [UIImage imageNamed:@"Closest_ATM.png"];

    }
    if (mapAnnotation.isOffline) {
        pinView.image = [UIImage imageNamed:@"Offline_ATM.png"];
    }
    pinView.annotation = annotation;
    return pinView;        

}else if ([custAttr isEqualToString:@"P"]) // POIs
{
    MKAnnotationView* pinView;
    pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIndentifer];

    pinView.canShowCallout = YES;
    pinView.image = [UIImage imageNamed:@"Location_POI.png"];
    pinView.annotation = annotation;
    return pinView;
}

return nil;
}

How can I resolve this issue? Is there a way that I can prevent it from calling this method when zooming in/out or is there another way to let it draw them again as in the same image?

回答1:

The custAttr variable (which you are setting outside the delegate method) will not always be in sync with the annotation that the viewForAnnotation delegate method is called for.

The delegate method is not necessarily called right after addAnnotation or addAnnotations and can be called multiple times for each annotation if the map needs to display the annotation view again after a zoom or pan.

When it gets called again for the same annotation, the custAttr variable no longer matches up.


You need to add a custAttr property (I suggest using a different name) to your MapAnnotation class and set it when creating the annotation (before calling addAnnotation).

For example:

MapAnnotation *ann = [[MapAnnotation alloc] init];
ann.coordinate = ...
ann.title = ...
ann.subtitle = ...
ann.custAttr = custAttr; // <-- copy to the annotation object itself
[mapView addAnnotation:ann];


Then, in viewForAnnotation, read the custAttr property from the annotation parameter (after casting it to MapAnnotation *) instead of referencing the externally declared custAttr.

You may want to use a different name for the custAttr property in MapAnnotation to avoid confusion.