Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Fix crash getting annotation view #6957

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2865,19 +2865,13 @@ - (void)removeStyleClass:(NSString *)styleClass
/// Returns the annotation tag assigned to the given annotation. Relatively expensive.
- (MGLAnnotationTag)annotationTagForAnnotation:(id <MGLAnnotation>)annotation
{
if ( ! annotation || annotation == self.userLocation)
if ( ! annotation || annotation == self.userLocation
|| _annotationTagsByAnnotation.count(annotation) == 0)
{
return MGLAnnotationTagNotFound;
}

for (auto &pair : _annotationContextsByAnnotationTag)
{
if (pair.second.annotation == annotation)
{
return pair.first;
}
}
return MGLAnnotationTagNotFound;

return _annotationTagsByAnnotation.at(annotation);
}

- (void)addAnnotation:(id <MGLAnnotation>)annotation
Expand Down Expand Up @@ -3101,7 +3095,14 @@ - (MGLAnnotationView *)annotationViewForAnnotation:(id<MGLAnnotation>)annotation

- (nullable MGLAnnotationView *)viewForAnnotation:(id<MGLAnnotation>)annotation
{
MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation);
if (annotation == self.userLocation)
{
return self.userLocationAnnotationView;
}
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
if (annotationTag == MGLAnnotationTagNotFound) {
return nil;
}
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
return annotationContext.annotationView;
}
Expand Down Expand Up @@ -4675,9 +4676,9 @@ - (void)updateAnnotationViews
continue;
}

// Get the annotation tag then use it to get the context. This avoids the expensive lookup
// by tag in `annotationTagForAnnotation:`
MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation);
// Get the annotation tag then use it to get the context.
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
NSAssert(annotationTag != MGLAnnotationTagNotFound, @"-visibleAnnotationsInRect: returned unrecognized annotation");
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);

MGLAnnotationView *annotationView = annotationContext.annotationView;
Expand Down Expand Up @@ -4721,7 +4722,8 @@ - (void)updateAnnotationViews
continue;
}

MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation);
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
NSAssert(annotationTag != MGLAnnotationTagNotFound, @"-visibleAnnotationsInRect: returned unrecognized annotation");
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
UIView *annotationView = annotationContext.annotationView;

Expand Down
18 changes: 11 additions & 7 deletions platform/macos/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#import <mbgl/util/chrono.hpp>
#import <mbgl/util/run_loop.hpp>

#import <map>
#import <unordered_map>
#import <unordered_set>

Expand Down Expand Up @@ -110,6 +111,9 @@
/// the annotation itself.
typedef std::unordered_map<MGLAnnotationTag, MGLAnnotationContext> MGLAnnotationTagContextMap;

/// Mapping from an annotation object to an annotation tag.
typedef std::map<id<MGLAnnotation>, MGLAnnotationTag> MGLAnnotationObjectTagMap;

/// Returns an NSImage for the default marker image.
NSImage *MGLDefaultMarkerImage() {
NSString *path = [[NSBundle mgl_frameworkBundle] pathForResource:MGLDefaultStyleMarkerSymbolName
Expand Down Expand Up @@ -172,6 +176,7 @@ @implementation MGLMapView {
BOOL _didHideCursorDuringGesture;

MGLAnnotationTagContextMap _annotationContextsByAnnotationTag;
MGLAnnotationObjectTagMap _annotationTagsByAnnotation;
MGLAnnotationTag _selectedAnnotationTag;
MGLAnnotationTag _lastSelectedAnnotationTag;
/// Size of the rectangle formed by unioning the maximum slop area around every annotation image.
Expand Down Expand Up @@ -293,6 +298,7 @@ - (void)commonInit {
// Set up annotation management and selection state.
_annotationImagesByIdentifier = [NSMutableDictionary dictionary];
_annotationContextsByAnnotationTag = {};
_annotationTagsByAnnotation = {};
_selectedAnnotationTag = MGLAnnotationTagNotFound;
_lastSelectedAnnotationTag = MGLAnnotationTagNotFound;
_annotationsNearbyLastClick = {};
Expand Down Expand Up @@ -1661,16 +1667,11 @@ - (IBAction)rotate:(NSSlider *)sender {

/// Returns the annotation tag assigned to the given annotation. Relatively expensive.
- (MGLAnnotationTag)annotationTagForAnnotation:(id <MGLAnnotation>)annotation {
if (!annotation) {
if (!annotation || _annotationTagsByAnnotation.count(annotation) == 0) {
return MGLAnnotationTagNotFound;
}

for (auto &pair : _annotationContextsByAnnotationTag) {
if (pair.second.annotation == annotation) {
return pair.first;
}
}
return MGLAnnotationTagNotFound;
return _annotationTagsByAnnotation.at(annotation);
}

- (void)addAnnotation:(id <MGLAnnotation>)annotation {
Expand Down Expand Up @@ -1708,6 +1709,7 @@ - (void)addAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations {
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
_annotationTagsByAnnotation[annotation] = annotationTag;

[(NSObject *)annotation addObserver:self forKeyPath:@"coordinates" options:0 context:(void *)(NSUInteger)annotationTag];
} else if (![annotation isKindOfClass:[MGLMultiPolyline class]]
Expand Down Expand Up @@ -1745,6 +1747,7 @@ - (void)addAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations {
context.annotation = annotation;
context.imageReuseIdentifier = annotationImage.reuseIdentifier;
_annotationContextsByAnnotationTag[annotationTag] = context;
_annotationTagsByAnnotation[annotation] = annotationTag;

if ([annotation isKindOfClass:[NSObject class]]) {
NSAssert(![annotation isKindOfClass:[MGLMultiPoint class]], @"Point annotation should not be MGLMultiPoint.");
Expand Down Expand Up @@ -1831,6 +1834,7 @@ - (void)removeAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations {
}

_annotationContextsByAnnotationTag.erase(annotationTag);
_annotationTagsByAnnotation.erase(annotation);

if ([annotation isKindOfClass:[NSObject class]] &&
![annotation isKindOfClass:[MGLMultiPoint class]]) {
Expand Down