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

Commit

Permalink
[ios] Observe annotation coordinates
Browse files Browse the repository at this point in the history
MGLMapView observes changes to the coordinate property of each MGLAnnotation added to it. Changing the coordinate property in a KVO-compliant way causes the annotation to be relocated and its callout view, if present, to be dismissed. To avoid observing the same annotation twice yet also avoid expensive lookups when adding or removing annotations, MGLMapView indexes added point annotations in an NSMutableSet.

In iosapp, tapping a callout view moves the selected annotation to the center of the screen and deselects it.

Fixes #1980.
  • Loading branch information
1ec5 committed Apr 17, 2016
1 parent 62a4e25 commit 7401aab
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
1 change: 1 addition & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Mapbox welcomes participation and contributions from everyone. If you’d like
- Applications linking against the SDK static framework no longer need to add `-ObjC` to the Other Linker Flags (`OTHER_LDFLAGS`) build setting. If you previously added this flag solely for this SDK, removing the flag may potentially reduce the overall size of your application. ([#4641](https://github.com/mapbox/mapbox-gl-native/pull/4641))
- Removed the `armv7s` slice from the SDK to reduce its size. iPhone 5 and iPhone 5c automatically use the `armv7` slice instead. ([#4641](https://github.com/mapbox/mapbox-gl-native/pull/4641))
- User location heading updates now resume properly when an app becomes active again. ([#4674](https://github.com/mapbox/mapbox-gl-native/pull/4674))
- An MGLAnnotation can be relocated by changing its `coordinate` property in a KVO-compliant way. ([#3835](https://github.com/mapbox/mapbox-gl-native/pull/3835))
- Setting the `image` property of an MGLAnnotationImage to `nil` resets it to the default red pin image and reclaims resources that can be used to customize additional annotations. ([#3835](https://github.com/mapbox/mapbox-gl-native/pull/3835))
- A more specific user agent string is now sent with style and tile requests. ([#4012](https://github.com/mapbox/mapbox-gl-native/pull/4012))
- Removed unused SVG files from the SDK’s resource bundle. ([#4641](https://github.com/mapbox/mapbox-gl-native/pull/4641))
Expand Down
11 changes: 11 additions & 0 deletions platform/ios/app/MBXViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -695,4 +695,15 @@ - (void)mapView:(__unused MGLMapView *)mapView didChangeUserTrackingMode:(MGLUse
return nil;
}

- (void)mapView:(MGLMapView *)mapView tapOnCalloutForAnnotation:(id <MGLAnnotation>)annotation
{
if ( ! [annotation isKindOfClass:[MGLPointAnnotation class]])
{
return;
}

MGLPointAnnotation *point = annotation;
point.coordinate = [self.mapView convertPoint:self.mapView.center toCoordinateFromView:self.mapView];
}

@end
29 changes: 29 additions & 0 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ @implementation MGLMapView
NS_MUTABLE_ARRAY_OF(NSURL *) *_bundledStyleURLs;

MGLAnnotationContextMap _annotationContextsByAnnotationTag;
NS_MUTABLE_SET_OF(id <MGLAnnotation>) *_pointAnnotations;
/// Tag of the selected annotation. If the user location annotation is selected, this ivar is set to `MGLAnnotationTagNotFound`.
MGLAnnotationTag _selectedAnnotationTag;
BOOL _userLocationAnnotationIsSelected;
Expand Down Expand Up @@ -337,6 +338,7 @@ - (void)commonInit
// Set up annotation management and selection state.
_annotationImagesByIdentifier = [NSMutableDictionary dictionary];
_annotationContextsByAnnotationTag = {};
_pointAnnotations = [NSMutableSet set];
_selectedAnnotationTag = MGLAnnotationTagNotFound;
_annotationsNearbyLastTap = {};

Expand Down Expand Up @@ -1609,6 +1611,21 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
[MGLMapboxEvents ensureMetricsOptoutExists];
}
}
else if ([keyPath isEqualToString:@"coordinate"] && [object conformsToProtocol:@protocol(MGLAnnotation)])
{
id <MGLAnnotation> annotation = object;
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
if (annotationTag != MGLAnnotationTagNotFound)
{
const mbgl::LatLng latLng = MGLLatLngFromLocationCoordinate2D(annotation.coordinate);
MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
_mbglMap->updatePointAnnotation(annotationTag, { latLng, annotationImage.styleIconIdentifier.UTF8String ?: "" });
if (annotationTag == _selectedAnnotationTag)
{
[self deselectAnnotation:annotation animated:YES];
}
}
}
}

+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingZoomEnabled
Expand Down Expand Up @@ -2418,6 +2435,12 @@ - (void)addAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations
[annotationImages addObject:annotationImage];

points.emplace_back(MGLLatLngFromLocationCoordinate2D(annotation.coordinate), symbolName.UTF8String ?: "");

if ( ! [_pointAnnotations containsObject:annotation] && [annotation isKindOfClass:[NSObject class]])
{
[(NSObject *)annotation addObserver:self forKeyPath:@"coordinate" options:0 context:NULL];
[_pointAnnotations addObject:annotation];
}
}
}

Expand Down Expand Up @@ -2572,6 +2595,12 @@ - (void)removeAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations
}

_annotationContextsByAnnotationTag.erase(annotationTag);

if ([annotation isKindOfClass:[NSObject class]])
{
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinate"];
}
[_pointAnnotations removeObject:annotation];
}

if ( ! annotationTagsToRemove.empty())
Expand Down

0 comments on commit 7401aab

Please sign in to comment.