MKAnnotationView image changing issue

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-11 12:30:05

问题


I've got an MKMapView loaded with plenty of custom annotation (800 circa).

When I drag on the map and I return to an annotation, it's image has changed with another one. For me it's seems like a cache issue.

Pin before dragging

Pin after dragging

SuperClass header

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MapAnnotation : NSObject <MKAnnotation>

@property (nonatomic, copy) NSString *title;
@property NSString * pinImageName;
@property (nonatomic) CLLocationCoordinate2D coordinate;

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title pinImageName:(NSString *)pinImageName;

- (MKAnnotationView *)getAnnotationView;
@end

SubClass (the one that creates the issue) header

#import "MapAnnotation.h"
#import "Company.h"

@interface CompanyAnnotation : MapAnnotation

@property Company *company;
@property UIImage *pinImage;

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title pinImage:(UIImage *)pinImage;
- (MKAnnotationView *)getAnnotationView;

@end

viewForAnnotation delegate method

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation {
    if (annotation == mapView.userLocation){
        return nil;
    }

    MapAnnotation *location = [MapAnnotation new];
    MKAnnotationView *annotationView = [MKAnnotationView new];

    if ([annotation isKindOfClass:[CompanyAnnotation class]]) {
        location = (CompanyAnnotation *)annotation;
        annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"companyAnnotation"];
    }

    if (annotationView == nil) {
        annotationView = [location getAnnotationView];
    } else {
        annotationView.annotation = annotation;
    }
    return annotationView;
}

getAnnotationView method

- (MKAnnotationView *)getAnnotationView {
    MKAnnotationView * annotationView = [[MKAnnotationView alloc] initWithAnnotation:self reuseIdentifier:@"companyAnnotation"];
    [annotationView setEnabled:YES];
    [annotationView setCanShowCallout:YES];
    [annotationView setContentMode:UIViewContentModeScaleAspectFit];
    [annotationView setImage:self.pinImage];
    [annotationView setFrame:CGRectMake(0, 0, 28, 44)];
    [annotationView setRightCalloutAccessoryView:[UIButton buttonWithType:UIButtonTypeDetailDisclosure]];

    return annotationView;
}

回答1:


The dequeue is not being handled properly in viewForAnnotation because when dequeueReusableAnnotationViewWithIdentifier returns a previously-used view (when annotationView is not nil), the code is only updating that view's annotation property:

if (annotationView == nil) {
    annotationView = [location getAnnotationView];
} else {
    annotationView.annotation = annotation;
}

But the annotation view's image is not updated -- in a dequeued view, the image will be set to the one associated with the annotation the view was originally created for (when getAnnotationView was called).

So now the view appears at the new annotation's coordinates but the image is still from the previous annotation the view was used for.


There are various ways to fix this such as creating a proper subclass of MKAnnotationView that monitors changes to its annotation property and automatically updates all other properties associated with an annotation.

With the existing code, a simple way to fix it is to separate out the annotation-specific property changes into a separate method that can be called both when the view is created and when its annotation property is updated.

For example, in CompanyAnnotation, create a method like this:

-(void)configureView:(MKAnnotationView *)av
{
    av.image = self.pinImage;
}

Then change getAnnotationView to:

- (MKAnnotationView *)getAnnotationView {
    MKAnnotationView * annotationView = [[MKAnnotationView alloc] initWithAnnotation:self reuseIdentifier:@"companyAnnotation"];

    //set properties here that are not specific to an annotation...
    [annotationView setEnabled:YES];
    [annotationView setCanShowCallout:YES];
    [annotationView setContentMode:UIViewContentModeScaleAspectFit];
    //[annotationView setImage:self.pinImage];
    [annotationView setFrame:CGRectMake(0, 0, 28, 44)];
    [annotationView setRightCalloutAccessoryView:[UIButton buttonWithType:UIButtonTypeDetailDisclosure]];

    //set properties that are specific to an annotation...
    [self configureView:annotationView];

    return annotationView;
}

Finally in viewForAnnotation:

if (annotationView == nil) {
    annotationView = [location getAnnotationView];
} else {
    annotationView.annotation = annotation;

    if ([annotation isKindOfClass:[CompanyAnnotation class]]) {
        //update image, etc...
        [annotation configureView:annotationView];
    }
}

Note that MapAnnotation will have the same issue with the pinImageName property.



来源:https://stackoverflow.com/questions/30122625/mkannotationview-image-changing-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!