我如何解决导致重复标注的MapKit错误?

时间:2015-01-16 23:06:47

标签: cocoa cocoa-touch mapkit

有一个bug in MapKit that can cause duplicate callout views on an annotation。如果时间恰到好处,则注释视图可以在被选中时重复使用,并且显然恰好在实际添加了标注视图之前。结果,旧的标注视图卡在那里,新的标注将出现在它的顶部或旁边。以下是OS X应用程序中的内容:

enter image description here

此地图上只有一个注释。如果单击地图上的其他位置以取消选择注释,则只有一个标注消失。在某些情况下,您可能会有两个具有完全不同信息的标注,这对于使用您的应用的人来说会让您感到困惑。

这是我放在一起的示例OS X项目的大部分内容,它说明了这个错误:

@import MapKit;
#import "AppDelegate.h"
#import "JUNMapAnnotation.h"

@interface AppDelegate () <MKMapViewDelegate>

@property (weak) IBOutlet NSWindow *window;
@property (weak) IBOutlet MKMapView *mapView;
@property BOOL firstPin;

- (void)placeAndSelectPin;
- (JUNMapAnnotation *)placePin;
- (void)clearPins;

@end

@implementation AppDelegate

- (IBAction)dropSomePins:(id)sender {
    self.firstPin = YES;
    [self placeAndSelectPin];
    [self performSelector:@selector(placeAndSelectPin) withObject:nil afterDelay:0.0001];
}

#pragma mark - Private methods

- (void)placeAndSelectPin {
    [self clearPins];
    JUNMapAnnotation *annotation = [self placePin];
    [self.mapView deselectAnnotation:annotation animated:NO];
    [self.mapView selectAnnotation:annotation animated:YES];
}

- (JUNMapAnnotation *)placePin {
    CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(50.0,50.0);
    JUNMapAnnotation *annotation = [[JUNMapAnnotation alloc] initWithCoordinate:coord];
    annotation.title = @"Annotation";
    annotation.subtitle = (self.firstPin) ? @"This is an annotation with a longer subtitle" : @"This is an annotation";
    [self.mapView addAnnotation:annotation];
    self.firstPin = NO;
    return annotation;
}

- (void)clearPins {
    [self.mapView removeAnnotations:self.mapView.annotations];
}

#pragma mark - MKMapViewDelegate

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if ([annotation isKindOfClass:[JUNMapAnnotation class]]) {

        static NSString *identifier = @"annotationView";
        MKPinAnnotationView *view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
        if (view == nil) {
            view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
            view.canShowCallout = YES;
            NSLog(@"new annotation view");
        } else {
            view.annotation = annotation;
        }
        return view;

    }
    return nil;
}

@end

iOS中似乎存在同样的错误,但我在那里重新创建它的时间更为艰难。

虽然我在等苹果公司解决这个问题,但我希望尽可能地解决这个问题。到目前为止,我已经提出了一些可能性:

  1. 不要重复使用注释视图。据我所知,这似乎是完全避免这个错误的唯一方法,但它看起来效率很低。
  2. mapView:viewForAnnotation:中重复使用注释视图时,请删除其所有子视图。目前似乎标注是唯一的子视图,尽管它似乎并不是一个特别安全的黑客。它也只是一些作品 - 它不会阻止重复的标注出现,它只是让它们永远不会粘在一起。 (当这个bug第一次发生时,实际上还没有任何子视图。)
  3. 将两者结合起来:如果dequeueReusableAnnotationViewWithIdentifier:返回包含任何子视图的视图,请忽略它并创建一个新视图。这似乎比2更安全,并且几乎没有1那么低效。但与2一样,它不是一个完整的解决方法。
  4. 我也尝试在我能想到的每个地方添加deselectAnnotation:animated:,但我找不到任何可行的地方。我假设一旦重复使用注释视图,MapView就会丢失第一个标注的跟踪,因此它的常规方法都不会消除它。

1 个答案:

答案 0 :(得分:1)

这有点偏离了场,但是...... 尝试使用2个不同的重用标识符注册相同的单元类。在viewForAnnotation:中,在出列单元格时使用每个标识符之间交替。这应该可以防止连续两次从同一队列中获取。