MKAnnotationView 图像更改问题

MKAnnotationView image changing issue

我有一个加载了大量自定义注释的 MKMapView(大约 800)。

当我在地图上拖动并 return 到注释时,它的图像已与另一个不同。对我来说,这似乎是一个缓存问题。

拖动前固定

拖动后固定

超类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

子类(产生问题的那个)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 委托方法

- (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 方法

- (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;
}

viewForAnnotation 中未正确处理出队,因为当 dequeueReusableAnnotationViewWithIdentifier returns 以前使用过视图(当 annotationView 不是 nil 时) ,代码仅更新该视图的 annotation 属性:

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

但是注释视图的 image 没有更新——在出队视图中,image 将被设置为与注释视图相关联的视图最初 为(调用 getAnnotationView 时)创建。

所以现在视图出现在新注释的坐标处,但图像仍然来自以前使用该视图的注释。


有多种方法可以解决此问题,例如创建 MKAnnotationView 的适当子类来监视对其 annotation 属性 的更改并自动更新与注释关联的所有其他属性。

使用现有代码,修复它的一个简单方法是将特定于注释的 属性 更改分离到一个单独的方法中,该方法可以在创建视图时及其 annotation 属性 已更新。

例如,在CompanyAnnotation中,创建一个这样的方法:

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

然后将getAnnotationView改为:

- (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;
}

终于在 viewForAnnotation:

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

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

请注意 MapAnnotation 将与 pinImageName 属性 有相同的问题。