MKMapView Off Screen Annotation Image Incorrect

2019-03-02 21:39发布

问题:

I have a map to which I add several annotations, like so:

    for (Users *user in mapUsers){

        double userlat = [user.llat doubleValue];
        double userLong = [user.llong doubleValue];

        CLLocationCoordinate2D userCoord = {.latitude =  userlat, .longitude =  userLong};

        MapAnnotationViewController *addAnnotation = [[MapAnnotationViewController alloc] initWithCoordinate:userCoord];

        NSString *userName = user.username;
        NSString *relationship = user.relationship;

        [addAnnotation setTitle:userName];
        [addAnnotation setRelationshipParam:relationship];

        [self.mainMapView addAnnotation:addAnnotation];
    }

Using this delegate method code:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    static NSString *identifier = @"AnnotationIdentifier";

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

    MKAnnotationView *annView = (MKAnnotationView *)[self.mainMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    if (!annView) {
        annView = [[MKAnnotationView alloc] initWithAnnotation:annotation
                                                          reuseIdentifier:identifier];
    }
    MapAnnotationViewController *sac = (MapAnnotationViewController *)annView.annotation;

    if ([sac.relationshipParam isEqualToString:@"paramA"])
    {
        annView.image = [UIImage imageNamed:@"image1.png"];
    }
    else if ([sac.relationshipParam isEqualToString:@"paramB"])
    {
        annView.image = [UIImage imageNamed:@"image2.png"];
    }
    else if ([sac.relationshipParam isEqualToString:@"paramC"])
    {
        annView.image = [UIImage imageNamed:@"image3.png"];
    }


    return annView;
}
else {
    return nil;
}

This all works fine on the original loading of the map. However, when I select the annotation (which has custom code that is too long to post but includes a zoom in) the annotation images that were previously drawn have changed icons. The map is not redrawn and the annotations are not re-added in that process. When I pinch back out on the map, the images are different (they have match the incorrect relationship params with the wrong image1-3.png's.

Can anyone think of why this is happening, or what to look for?

回答1:

The dequeueReusableAnnotationViewWithIdentifier may return an annotation view that was used for an annotation different from the current annotation parameter.

If the dequeueReusableAnnotationViewWithIdentifier is succesful (ie. you're using a previously-used annotation view), you must update its annotation property to be sure the view matches the current annotation's properties.

So try changing this part:

MKAnnotationView *annView = (MKAnnotationView *)[self.mainMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annView) {
    annView = [[MKAnnotationView alloc] initWithAnnotation:annotation
                                                      reuseIdentifier:identifier];
}
MapAnnotationViewController *sac = (MapAnnotationViewController *)annView.annotation;

to:

MKAnnotationView *annView = (MKAnnotationView *)[self.mainMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annView) {
    annView = [[MKAnnotationView alloc] initWithAnnotation:annotation
                                                      reuseIdentifier:identifier];
}
else {
    annView.annotation = annotation; // <-- add this
}

MapAnnotationViewController *sac = (MapAnnotationViewController *)annView.annotation;


Another potential issue (not causing the problem in the question) is that the view's image property is only set if relationshipParam is one of three values.

If somehow relationshipParam is not one of those three coded values and the view was dequeued, the image will be based on some other annotation's relationshipParam.

So you should add an else part to the section that sets image and set it to some default image just in case:

...
else if ([sac.relationshipParam isEqualToString:@"paramC"])
{
    annView.image = [UIImage imageNamed:@"image3.png"];
}
else
{
    annView.image = [UIImage imageNamed:@"UnknownRelationship.png"];
}