summaryrefslogtreecommitdiff
path: root/platform/ios
diff options
context:
space:
mode:
authorJulian Rex <julian.rex@gmail.com>2018-04-24 11:01:04 -0400
committerGitHub <noreply@github.com>2018-04-24 11:01:04 -0400
commit5b5549d644d026e093243b13e0770b9d34172ef9 (patch)
tree58aa4bc9cbc7cd78f00f4b2aed38570a21568717 /platform/ios
parentfa6c6a3733323e855c1b825c9546093200cf0d62 (diff)
downloadqtlocation-mapboxgl-5b5549d644d026e093243b13e0770b9d34172ef9.tar.gz
[ios, macos] Fix for camera movement when selecting visible annotations (#11731)
Diffstat (limited to 'platform/ios')
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme10
-rw-r--r--platform/ios/src/MGLMapView.mm21
-rw-r--r--platform/ios/test/MGLAnnotationViewTests.m89
3 files changed, 115 insertions, 5 deletions
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
index 4679378126..afba168676 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
@@ -54,7 +54,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -66,6 +65,14 @@
BlueprintName = "test"
ReferencedContainer = "container:ios.xcodeproj">
</BuildableReference>
+ <SkippedTests>
+ <Test
+ Identifier = "MGLAnnotationViewTests/testAnnotationViewInitWithFrame">
+ </Test>
+ <Test
+ Identifier = "MGLAnnotationViewTests/testSelectingADisabledAnnotationView">
+ </Test>
+ </SkippedTests>
</TestableReference>
</Testables>
<MacroExpansion>
@@ -84,7 +91,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index b7d0974872..c679979d37 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -4290,6 +4290,15 @@ public:
moveOnscreen = [self isBringingAnnotationOnscreenSupportedForAnnotation:annotation animated:animateSelection];
}
+ // If we have an invalid positioning rect, we need to provide a suitable default.
+ // This (currently) happens if you select an annotation that has NOT yet been
+ // added. See https://github.com/mapbox/mapbox-gl-native/issues/11476
+ if (CGRectIsNull(calloutPositioningRect)) {
+ CLLocationCoordinate2D origin = annotation.coordinate;
+ CGPoint originPoint = [self convertCoordinate:origin toPointToView:self];
+ calloutPositioningRect = { .origin = originPoint, .size = CGSizeZero };
+ }
+
CGRect expandedPositioningRect = UIEdgeInsetsInsetRect(calloutPositioningRect, MGLMapViewOffscreenAnnotationPadding);
// Used for callout positioning, and moving offscreen annotations onscreen.
@@ -4442,7 +4451,11 @@ public:
{
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
CGRect positioningRect = [self positioningRectForCalloutForAnnotationWithTag:annotationTag];
-
+
+ if (CGRectIsNull(positioningRect)) {
+ return positioningRect;
+ }
+
// For annotations which `coordinate` falls offscreen it will use the current tap point as anchor instead.
if ( ! CGRectIntersectsRect(positioningRect, self.bounds) && annotation != self.userLocation)
{
@@ -4462,15 +4475,15 @@ public:
id <MGLAnnotation> annotation = [self annotationWithTag:annotationTag];
if ( ! annotation)
{
- return CGRectZero;
+ return CGRectNull;
}
if ([annotation isKindOfClass:[MGLMultiPoint class]]) {
CLLocationCoordinate2D origin = annotation.coordinate;
CGPoint originPoint = [self convertCoordinate:origin toPointToView:self];
return CGRectMake(originPoint.x, originPoint.y, MGLAnnotationImagePaddingForHitTest, MGLAnnotationImagePaddingForHitTest);
-
}
+
UIImage *image = [self imageOfAnnotationWithTag:annotationTag].image;
if ( ! image)
{
@@ -5743,6 +5756,8 @@ public:
rect = annotationView.frame;
}
+ NSAssert(!CGRectIsNull(rect), @"Positioning rect should not be CGRectNull by this point");
+
CGPoint point = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
if ( ! CGPointEqualToPoint(calloutView.center, point)) {
diff --git a/platform/ios/test/MGLAnnotationViewTests.m b/platform/ios/test/MGLAnnotationViewTests.m
index 2f5963e66e..a2cc4227ed 100644
--- a/platform/ios/test/MGLAnnotationViewTests.m
+++ b/platform/ios/test/MGLAnnotationViewTests.m
@@ -3,6 +3,13 @@
static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReuseIdentifer";
+
+@interface MGLMapView (Tests)
+@property (nonatomic) MGLCameraChangeReason cameraChangeReasonBitmask;
+@end
+
+
+
@interface MGLCustomAnnotationView : MGLAnnotationView
@end
@@ -58,6 +65,7 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
@property (nonatomic) MGLMapView *mapView;
@property (nonatomic, weak) MGLAnnotationView *annotationView;
@property (nonatomic) NSInteger annotationSelectedCount;
+@property (nonatomic) void (^prepareAnnotationView)(MGLAnnotationView*);
@end
@implementation MGLAnnotationViewTests
@@ -152,6 +160,83 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
XCTAssertEqual(selectionCount, self.annotationSelectedCount, @"-mapView:didSelectAnnotation: should be called for each selection");
}
+- (void)testSelectingOnscreenAnnotationThatHasNotBeenAdded {
+ // See https://github.com/mapbox/mapbox-gl-native/issues/11476
+
+ // This bug occurs under the following conditions:
+ //
+ // - There are content insets (e.g. navigation bar) for the compare against
+ // CGRectZero (now CGRectNull)
+ // - annotationView.enabled == NO - Currently this can happen if you use
+ // `-initWithFrame:` rather than one of the provided initializers
+ //
+
+ self.prepareAnnotationView = ^(MGLAnnotationView *view) {
+ view.enabled = NO;
+ };
+
+ self.mapView.contentInset = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
+
+ MGLCameraChangeReason reasonBefore = self.mapView.cameraChangeReasonBitmask;
+ XCTAssert(reasonBefore == MGLCameraChangeReasonNone, @"Camera should not have moved at start of test");
+
+ // Create annotation
+ MGLPointFeature *point = [[MGLPointFeature alloc] init];
+ point.title = NSStringFromSelector(_cmd);
+ point.coordinate = CLLocationCoordinate2DMake(0.0, 0.0);
+
+ MGLCoordinateBounds coordinateBounds = [self.mapView convertRect:self.mapView.bounds toCoordinateBoundsFromView:self.mapView];
+ XCTAssert(MGLCoordinateInCoordinateBounds(point.coordinate, coordinateBounds), @"The test point should be within the visible map view");
+
+ // Select on screen annotation (DO NOT ADD FIRST).
+ [self.mapView selectAnnotation:point animated:YES];
+
+ // Expect - the camera NOT to move.
+ MGLCameraChangeReason reasonAfter = self.mapView.cameraChangeReasonBitmask;
+ XCTAssert(reasonAfter == MGLCameraChangeReasonNone, @"Camera should not have moved");
+}
+
+- (void)checkDefaultPropertiesForAnnotationView:(MGLAnnotationView*)view {
+ XCTAssertNil(view.annotation);
+ XCTAssertNil(view.reuseIdentifier);
+ XCTAssertEqual(view.centerOffset.dx, 0.0);
+ XCTAssertEqual(view.centerOffset.dy, 0.0);
+ XCTAssertFalse(view.scalesWithViewingDistance);
+ XCTAssertFalse(view.rotatesToMatchCamera);
+ XCTAssertFalse(view.isSelected);
+ XCTAssert(view.isEnabled);
+ XCTAssertFalse(view.isDraggable);
+ XCTAssertEqual(view.dragState, MGLAnnotationViewDragStateNone);
+}
+
+- (void)testAnnotationViewInitWithFrame {
+ CGRect frame = CGRectMake(10.0, 10.0, 100.0, 100.0);
+ MGLAnnotationView *view = [[MGLAnnotationView alloc] initWithFrame:frame];
+ [self checkDefaultPropertiesForAnnotationView:view];
+}
+
+- (void)testAnnotationViewInitWithReuseIdentifier {
+ MGLAnnotationView *view = [[MGLAnnotationView alloc] initWithReuseIdentifier:nil];
+ [self checkDefaultPropertiesForAnnotationView:view];
+}
+
+- (void)testSelectingADisabledAnnotationView {
+ self.prepareAnnotationView = ^(MGLAnnotationView *view) {
+ view.enabled = NO;
+ };
+
+ // Create annotation
+ MGLPointFeature *point = [[MGLPointFeature alloc] init];
+ point.title = NSStringFromSelector(_cmd);
+ point.coordinate = CLLocationCoordinate2DMake(0.0, 0.0);
+
+ XCTAssert(self.mapView.selectedAnnotations.count == 0, @"There should be 0 selected annotations");
+
+ [self.mapView selectAnnotation:point animated:NO];
+
+ XCTAssert(self.mapView.selectedAnnotations.count == 0, @"There should be 0 selected annotations");
+}
+
#pragma mark - MGLMapViewDelegate -
- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAnnotation>)annotation
@@ -163,6 +248,10 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
annotationView = [[MGLAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MGLTestAnnotationReuseIdentifer];
}
+ if (self.prepareAnnotationView) {
+ self.prepareAnnotationView(annotationView);
+ }
+
_annotationView = annotationView;
return annotationView;