summaryrefslogtreecommitdiff
path: root/platform/ios/src/MGLMapView.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ios/src/MGLMapView.mm')
-rw-r--r--platform/ios/src/MGLMapView.mm329
1 files changed, 231 insertions, 98 deletions
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 05168ea819..8ab612663c 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -94,6 +94,7 @@ const MGLMapViewPreferredFramesPerSecond MGLMapViewPreferredFramesPerSecondMaxim
const MGLExceptionName MGLMissingLocationServicesUsageDescriptionException = @"MGLMissingLocationServicesUsageDescriptionException";
const MGLExceptionName MGLUserLocationAnnotationTypeException = @"MGLUserLocationAnnotationTypeException";
const MGLExceptionName MGLResourceNotFoundException = @"MGLResourceNotFoundException";
+const MGLExceptionName MGLUnderlyingMapUnavailableException = @"MGLUnderlyingMapUnavailableException";
/// Indicates the manner in which the map view is tracking the user location.
typedef NS_ENUM(NSUInteger, MGLUserTrackingState) {
@@ -249,6 +250,14 @@ public:
@property (nonatomic) CFTimeInterval frameTime;
@property (nonatomic) CFTimeInterval averageFrameTime;
+/// Residual properties (saved on app termination)
+@property (nonatomic) BOOL terminated;
+@property (nonatomic, copy) MGLMapCamera *residualCamera;
+@property (nonatomic) MGLMapDebugMaskOptions residualDebugMask;
+@property (nonatomic, copy) NSURL *residualStyleURL;
+
+- (mbgl::Map &)mbglMap;
+
@end
@implementation MGLMapView
@@ -372,7 +381,13 @@ public:
- (nonnull NSURL *)styleURL
{
- NSString *styleURLString = @(_mbglMap->getStyle().getURL().c_str()).mgl_stringOrNilIfEmpty;
+ if (!_mbglMap)
+ {
+ NSAssert(self.terminated, @"_mbglMap should only be unavailable during app termination");
+ return self.residualStyleURL;
+ }
+
+ NSString *styleURLString = @(self.mbglMap.getStyle().getURL().c_str()).mgl_stringOrNilIfEmpty;
MGLAssert(styleURLString || _isTargetingInterfaceBuilder, @"Invalid style URL string %@", styleURLString);
return styleURLString ? [NSURL URLWithString:styleURLString] : nil;
}
@@ -388,19 +403,24 @@ public:
MGLLogDebug(@"Setting styleURL: %@", styleURL);
styleURL = styleURL.mgl_URLByStandardizingScheme;
self.style = nil;
- _mbglMap->getStyle().loadURL([[styleURL absoluteString] UTF8String]);
+ self.mbglMap.getStyle().loadURL([[styleURL absoluteString] UTF8String]);
}
- (IBAction)reloadStyle:(__unused id)sender {
MGLLogInfo(@"Reloading style.");
NSURL *styleURL = self.styleURL;
- _mbglMap->getStyle().loadURL("");
+ self.mbglMap.getStyle().loadURL("");
self.styleURL = styleURL;
}
-- (mbgl::Map *)mbglMap
+- (mbgl::Map &)mbglMap
{
- return _mbglMap;
+ if (!_mbglMap)
+ {
+ [NSException raise:MGLUnderlyingMapUnavailableException
+ format:@"The underlying map is not available - this happens during app termination"];
+ }
+ return *_mbglMap;
}
- (mbgl::Renderer *)renderer
@@ -447,6 +467,8 @@ public:
auto renderer = std::make_unique<mbgl::Renderer>(*_mbglView, config.scaleFactor, *config.fileSource, *_mbglThreadPool, config.contextMode, config.cacheDir, config.localFontFamilyName);
BOOL enableCrossSourceCollisions = !config.perSourceCollisions;
_rendererFrontend = std::make_unique<MGLRenderFrontend>(std::move(renderer), self, *_mbglView);
+
+ NSAssert(!_mbglMap, @"_mbglMap should be NULL");
_mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *[config fileSource], *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default, enableCrossSourceCollisions);
// start paused if in IB
@@ -686,6 +708,26 @@ public:
_isWaitingForRedundantReachableNotification = NO;
}
+
+- (void)destroyCoreObjects {
+ // Record the current state. Currently only saving a limited set of properties.
+ self.terminated = YES;
+ self.residualCamera = self.camera;
+ self.residualDebugMask = self.debugMask;
+ self.residualStyleURL = self.styleURL;
+
+ // Tear down C++ objects, insuring worker threads correctly terminate.
+ // Because of how _mbglMap is constructed, we need to destroy it first.
+ delete _mbglMap;
+ _mbglMap = nullptr;
+
+ delete _mbglView;
+ _mbglView = nullptr;
+
+ _rendererFrontend.reset();
+ _mbglThreadPool.reset();
+}
+
- (void)dealloc
{
MGLLogInfo(@"Deallocating MGLMapView.");
@@ -704,17 +746,7 @@ public:
[self validateDisplayLink];
- if (_mbglMap)
- {
- delete _mbglMap;
- _mbglMap = nullptr;
- }
-
- if (_mbglView)
- {
- delete _mbglView;
- _mbglView = nullptr;
- }
+ [self destroyCoreObjects];
if ([[EAGLContext currentContext] isEqual:_context])
{
@@ -1017,8 +1049,8 @@ public:
[self adjustContentInset];
- if (!_isTargetingInterfaceBuilder) {
- _mbglMap->setSize([self size]);
+ if (!_isTargetingInterfaceBuilder && _mbglMap) {
+ self.mbglMap.setSize([self size]);
}
if (self.compassView.alpha)
@@ -1176,6 +1208,8 @@ public:
self.dormant = YES;
[self.glView deleteDrawable];
}
+
+ [self destroyCoreObjects];
}
- (void)validateDisplayLink
@@ -1183,9 +1217,9 @@ public:
BOOL isVisible = self.superview && self.window;
if (isVisible && ! _displayLink)
{
- if (_mbglMap->getConstrainMode() == mbgl::ConstrainMode::None)
+ if (_mbglMap && self.mbglMap.getConstrainMode() == mbgl::ConstrainMode::None)
{
- _mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
+ self.mbglMap.setConstrainMode(mbgl::ConstrainMode::HeightOnly);
}
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateFromDisplayLink)];
@@ -1385,7 +1419,7 @@ public:
return;
};
- _mbglMap->setGestureInProgress(false);
+ self.mbglMap.setGestureInProgress(false);
if (self.userTrackingState == MGLUserTrackingStateBegan)
{
[self setUserTrackingMode:MGLUserTrackingModeNone animated:NO];
@@ -1398,7 +1432,7 @@ public:
BOOL animated = NO;
[self cameraWillChangeAnimated:animated];
- _mbglMap->setGestureInProgress(true);
+ self.mbglMap.setGestureInProgress(true);
_changeDelimiterSuppressionDepth++;
}
@@ -1407,7 +1441,7 @@ public:
MGLAssert(_changeDelimiterSuppressionDepth >= 0,
@"Unbalanced change delimiter suppression/unsuppression");
if (_changeDelimiterSuppressionDepth == 0) {
- _mbglMap->setGestureInProgress(false);
+ self.mbglMap.setGestureInProgress(false);
}
if ( ! drift)
{
@@ -1463,7 +1497,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- _mbglMap->moveBy({ delta.x, delta.y });
+ self.mbglMap.moveBy({ delta.x, delta.y });
[pan setTranslation:CGPointZero inView:pan.view];
}
@@ -1486,7 +1520,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- _mbglMap->moveBy({ offset.x, offset.y }, MGLDurationFromTimeInterval(self.decelerationRate));
+ self.mbglMap.moveBy({ offset.x, offset.y }, MGLDurationFromTimeInterval(self.decelerationRate));
}
}
@@ -1521,7 +1555,7 @@ public:
{
[self trackGestureEvent:MMEEventGesturePinchStart forRecognizer:pinch];
- self.scale = powf(2, _mbglMap->getZoom());
+ self.scale = powf(2, self.mbglMap.getZoom());
[self notifyGestureDidBegin];
}
@@ -1536,7 +1570,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- _mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
+ self.mbglMap.setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
// The gesture recognizer only reports the gesture’s current center
// point, so use the previous center point to anchor the transition.
// If the number of touches has changed, the remembered center point is
@@ -1544,7 +1578,7 @@ public:
if (self.userTrackingMode == MGLUserTrackingModeNone && pinch.numberOfTouches == _previousPinchNumberOfTouches)
{
CLLocationCoordinate2D centerCoordinate = _previousPinchCenterCoordinate;
- _mbglMap->setLatLng(MGLLatLngFromLocationCoordinate2D(centerCoordinate),
+ self.mbglMap.setLatLng(MGLLatLngFromLocationCoordinate2D(centerCoordinate),
mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
}
@@ -1576,7 +1610,7 @@ public:
newScale += scale / (velocity * duration) * 0.1;
}
- if (newScale <= 0 || log2(newScale) < _mbglMap->getMinZoom())
+ if (newScale <= 0 || log2(newScale) < self.mbglMap.getMinZoom())
{
velocity = 0;
}
@@ -1595,7 +1629,7 @@ public:
{
if (drift)
{
- _mbglMap->setZoom(zoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationFromTimeInterval(duration));
+ self.mbglMap.setZoom(zoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationFromTimeInterval(duration));
}
}
@@ -1622,7 +1656,7 @@ public:
{
[self trackGestureEvent:MMEEventGestureRotateStart forRecognizer:rotate];
- self.angle = MGLRadiansFromDegrees(_mbglMap->getBearing()) * -1;
+ self.angle = MGLRadiansFromDegrees(self.mbglMap.getBearing()) * -1;
if (self.userTrackingMode != MGLUserTrackingModeNone)
{
@@ -1649,7 +1683,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- _mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
+ self.mbglMap.setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
[self cameraIsChanging];
@@ -1684,7 +1718,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- _mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationFromTimeInterval(decelerationRate));
+ self.mbglMap.setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationFromTimeInterval(decelerationRate));
[self notifyGestureDidEndWithDrift:YES];
@@ -1816,7 +1850,7 @@ public:
[self trackGestureEvent:MMEEventGestureDoubleTap forRecognizer:doubleTap];
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
- _mbglMap->setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration));
+ self.mbglMap.setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration));
__weak MGLMapView *weakSelf = self;
@@ -1837,7 +1871,7 @@ public:
if ( ! self.isZoomEnabled) return;
- if (_mbglMap->getZoom() == _mbglMap->getMinZoom()) return;
+ if (self.mbglMap.getZoom() == self.mbglMap.getMinZoom()) return;
[self cancelTransitions];
@@ -1856,7 +1890,7 @@ public:
[self trackGestureEvent:MMEEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
- _mbglMap->setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration));
+ self.mbglMap.setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration));
__weak MGLMapView *weakSelf = self;
@@ -1879,7 +1913,7 @@ public:
{
[self trackGestureEvent:MMEEventGestureQuickZoom forRecognizer:quickZoom];
- self.scale = powf(2, _mbglMap->getZoom());
+ self.scale = powf(2, self.mbglMap.getZoom());
self.quickZoomStart = [quickZoom locationInView:quickZoom.view].y;
@@ -1889,9 +1923,9 @@ public:
{
CGFloat distance = [quickZoom locationInView:quickZoom.view].y - self.quickZoomStart;
- CGFloat newZoom = MAX(log2f(self.scale) + (distance / 75), _mbglMap->getMinZoom());
+ CGFloat newZoom = MAX(log2f(self.scale) + (distance / 75), self.mbglMap.getMinZoom());
- if (_mbglMap->getZoom() == newZoom) return;
+ if (self.mbglMap.getZoom() == newZoom) return;
CGPoint centerPoint = [self anchorPointForGesture:quickZoom];
@@ -1900,7 +1934,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- _mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
+ self.mbglMap.setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
[self cameraIsChanging];
@@ -1929,7 +1963,7 @@ public:
if (twoFingerDrag.state == UIGestureRecognizerStateBegan || twoFingerDrag.state == UIGestureRecognizerStateChanged)
{
CGFloat gestureDistance = CGPoint([twoFingerDrag translationInView:twoFingerDrag.view]).y;
- CGFloat currentPitch = _mbglMap->getPitch();
+ CGFloat currentPitch = self.mbglMap.getPitch();
CGFloat slowdown = 20.0;
CGFloat pitchNew = currentPitch - (gestureDistance / slowdown);
@@ -1941,7 +1975,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- _mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
+ self.mbglMap.setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
[self cameraIsChanging];
@@ -1971,11 +2005,11 @@ public:
{
mbgl::ScreenCoordinate anchor = mbgl::ScreenCoordinate { anchorPoint.x, anchorPoint.y };
mbgl::EdgeInsets padding = mbgl::EdgeInsets(anchor.y, anchor.x, self.size.height - anchor.y, self.size.width - anchor.x);
- mbgl::CameraOptions currentCameraOptions = _mbglMap->getCameraOptions(padding);
+ mbgl::CameraOptions currentCameraOptions = self.mbglMap.getCameraOptions(padding);
currentCameraOptions.zoom = mbgl::util::clamp(zoom, self.minimumZoomLevel, self.maximumZoomLevel);
currentCameraOptions.anchor = anchor;
- MGLCoordinateBounds bounds = MGLCoordinateBoundsFromLatLngBounds(_mbglMap->latLngBoundsForCamera(currentCameraOptions));
+ MGLCoordinateBounds bounds = MGLCoordinateBoundsFromLatLngBounds(self.mbglMap.latLngBoundsForCamera(currentCameraOptions));
return [self cameraThatFitsCoordinateBounds:bounds];
}
@@ -1983,7 +2017,7 @@ public:
- (MGLMapCamera *)cameraByRotatingToDirection:(CLLocationDirection)degrees aroundAnchorPoint:(CGPoint)anchorPoint
{
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
- mbgl::CameraOptions currentCameraOptions = _mbglMap->getCameraOptions(padding);
+ mbgl::CameraOptions currentCameraOptions = self.mbglMap.getCameraOptions(padding);
MGLMapCamera *camera;
@@ -1998,7 +2032,7 @@ public:
- (MGLMapCamera *)cameraByTiltingToPitch:(CGFloat)pitch
{
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
- mbgl::CameraOptions currentCameraOptions = _mbglMap->getCameraOptions(padding);
+ mbgl::CameraOptions currentCameraOptions = self.mbglMap.getCameraOptions(padding);
MGLMapCamera *camera;
@@ -2292,7 +2326,7 @@ public:
NSString *symbolName = annotationImage.styleIconIdentifier;
// Update the annotation’s backing geometry to match the annotation model object. Any associated annotation view is also moved by side effect. However, -updateAnnotationViews disables the view’s animation actions, because it can’t distinguish between moves due to the viewport changing and moves due to the annotation’s coordinate changing.
- _mbglMap->updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, symbolName.UTF8String });
+ self.mbglMap.updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, symbolName.UTF8String });
[self updateCalloutView];
}
}
@@ -2310,7 +2344,7 @@ public:
if (annotation == [self annotationWithTag:annotationTag])
{
// Update the annotation’s backing geometry to match the annotation model object.
- _mbglMap->updateAnnotation(annotationTag, [annotation annotationObjectWithDelegate:self]);
+ self.mbglMap.updateAnnotation(annotationTag, [annotation annotationObjectWithDelegate:self]);
[self updateCalloutView];
}
}
@@ -2338,7 +2372,13 @@ public:
- (MGLMapDebugMaskOptions)debugMask
{
- mbgl::MapDebugOptions options = _mbglMap->getDebug();
+ if (!_mbglMap)
+ {
+ NSAssert(self.terminated, @"_mbglMap should only be unavailable during app termination");
+ return self.residualDebugMask;
+ }
+
+ mbgl::MapDebugOptions options = self.mbglMap.getDebug();
MGLMapDebugMaskOptions mask = 0;
if (options & mbgl::MapDebugOptions::TileBorders)
{
@@ -2365,6 +2405,11 @@ public:
- (void)setDebugMask:(MGLMapDebugMaskOptions)debugMask
{
+ if (!_mbglMap)
+ {
+ return;
+ }
+
mbgl::MapDebugOptions options = mbgl::MapDebugOptions::NoDebug;
if (debugMask & MGLMapDebugTileBoundariesMask)
{
@@ -2386,7 +2431,7 @@ public:
{
options |= mbgl::MapDebugOptions::Overdraw;
}
- _mbglMap->setDebug(options);
+ self.mbglMap.setDebug(options);
}
- (void)resetNorth
@@ -2403,7 +2448,7 @@ public:
- (void)resetPosition
{
MGLLogInfo(@"Resetting the map to the current style’s default viewport.");
- auto camera = _mbglMap->getStyle().getDefaultCamera();
+ auto camera = self.mbglMap.getStyle().getDefaultCamera();
CGFloat pitch = *camera.pitch;
CLLocationDirection heading = mbgl::util::wrap(*camera.angle, 0., 360.);
CLLocationDistance altitude = MGLAltitudeForZoomLevel(*camera.zoom, pitch, 0, self.frame.size);
@@ -2977,7 +3022,7 @@ public:
centerPoint = self.userLocationAnnotationViewCenter;
}
double newZoom = round(self.zoomLevel) + log2(scaleFactor);
- _mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
+ self.mbglMap.setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
[self unrotateIfNeededForGesture];
_accessibilityValueAnnouncementIsPending = YES;
@@ -3005,7 +3050,7 @@ public:
- (CLLocationCoordinate2D)centerCoordinate
{
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
- return MGLLocationCoordinate2DFromLatLng(_mbglMap->getLatLng(padding));
+ return MGLLocationCoordinate2DFromLatLng(self.mbglMap.getLatLng(padding));
}
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel animated:(BOOL)animated
@@ -3048,6 +3093,15 @@ public:
- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePadding:(UIEdgeInsets)insets zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
+ if (!_mbglMap)
+ {
+ if (completion)
+ {
+ completion();
+ }
+ return;
+ }
+
mbgl::CameraOptions cameraOptions;
cameraOptions.center = MGLLatLngFromLocationCoordinate2D(centerCoordinate);
cameraOptions.padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
@@ -3091,7 +3145,7 @@ public:
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
- _mbglMap->easeTo(cameraOptions, animationOptions);
+ self.mbglMap.easeTo(cameraOptions, animationOptions);
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingZoomLevel
@@ -3101,7 +3155,7 @@ public:
- (double)zoomLevel
{
- return _mbglMap->getZoom();
+ return self.mbglMap.getZoom();
}
- (void)setZoomLevel:(double)zoomLevel
@@ -3120,31 +3174,31 @@ public:
CGFloat duration = animated ? MGLAnimationDuration : 0;
- _mbglMap->setZoom(zoomLevel,
- MGLEdgeInsetsFromNSEdgeInsets(self.contentInset),
- MGLDurationFromTimeInterval(duration));
+ self.mbglMap.setZoom(zoomLevel,
+ MGLEdgeInsetsFromNSEdgeInsets(self.contentInset),
+ MGLDurationFromTimeInterval(duration));
}
- (void)setMinimumZoomLevel:(double)minimumZoomLevel
{
MGLLogDebug(@"Setting minimumZoomLevel: %f", minimumZoomLevel);
- _mbglMap->setMinZoom(minimumZoomLevel);
+ self.mbglMap.setMinZoom(minimumZoomLevel);
}
- (double)minimumZoomLevel
{
- return _mbglMap->getMinZoom();
+ return self.mbglMap.getMinZoom();
}
- (void)setMaximumZoomLevel:(double)maximumZoomLevel
{
MGLLogDebug(@"Setting maximumZoomLevel: %f", maximumZoomLevel);
- _mbglMap->setMaxZoom(maximumZoomLevel);
+ self.mbglMap.setMaxZoom(maximumZoomLevel);
}
- (double)maximumZoomLevel
{
- return _mbglMap->getMaxZoom();
+ return self.mbglMap.getMaxZoom();
}
- (MGLCoordinateBounds)visibleCoordinateBounds
@@ -3243,6 +3297,15 @@ public:
- (void)_setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
+ if (!_mbglMap)
+ {
+ if (completion)
+ {
+ completion();
+ }
+ return;
+ }
+
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
std::vector<mbgl::LatLng> latLngs;
@@ -3252,7 +3315,7 @@ public:
latLngs.push_back({coordinates[i].latitude, coordinates[i].longitude});
}
- mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngs(latLngs, padding);
+ mbgl::CameraOptions cameraOptions = self.mbglMap.cameraForLatLngs(latLngs, padding);
if (direction >= 0)
{
cameraOptions.angle = direction;
@@ -3290,7 +3353,7 @@ public:
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
- _mbglMap->easeTo(cameraOptions, animationOptions);
+ self.mbglMap.easeTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"visibleCoordinateBounds"];
}
@@ -3301,7 +3364,7 @@ public:
- (CLLocationDirection)direction
{
- return mbgl::util::wrap(_mbglMap->getBearing(), 0., 360.);
+ return mbgl::util::wrap(self.mbglMap.getBearing(), 0., 360.);
}
- (void)setDirection:(CLLocationDirection)direction animated:(BOOL)animated
@@ -3319,6 +3382,11 @@ public:
- (void)_setDirection:(CLLocationDirection)direction animated:(BOOL)animated
{
+ if (!_mbglMap)
+ {
+ return;
+ }
+
if (direction == self.direction) return;
[self cancelTransitions];
@@ -3328,14 +3396,14 @@ public:
if (self.userTrackingMode == MGLUserTrackingModeNone)
{
- _mbglMap->setBearing(direction,
+ self.mbglMap.setBearing(direction,
MGLEdgeInsetsFromNSEdgeInsets(self.contentInset),
MGLDurationFromTimeInterval(duration));
}
else
{
CGPoint centerPoint = self.userLocationAnnotationViewCenter;
- _mbglMap->setBearing(direction, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y },
+ self.mbglMap.setBearing(direction, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y },
MGLDurationFromTimeInterval(duration));
}
}
@@ -3358,8 +3426,14 @@ public:
- (MGLMapCamera *)camera
{
+ if (!_mbglMap)
+ {
+ NSAssert(self.terminated, @"_mbglMap should only be unavailable during app termination");
+ return self.residualCamera;
+ }
+
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
- return [self cameraForCameraOptions:_mbglMap->getCameraOptions(padding)];
+ return [self cameraForCameraOptions:self.mbglMap.getCameraOptions(padding)];
}
- (void)setCamera:(MGLMapCamera *)camera
@@ -3387,7 +3461,17 @@ public:
}
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function edgePadding:(UIEdgeInsets)edgePadding completionHandler:(nullable void (^)(void))completion {
+ if (!_mbglMap)
+ {
+ if (completion)
+ {
+ completion();
+ }
+ return;
+ }
+
MGLLogDebug(@"Setting camera: %@ duration: %f animationTimingFunction: %@ edgePadding: %@ completionHandler: %@", camera, duration, function, NSStringFromUIEdgeInsets(edgePadding), completion);
+
mbgl::AnimationOptions animationOptions;
if (duration > 0)
{
@@ -3420,7 +3504,7 @@ public:
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:edgePadding];
- _mbglMap->easeTo(cameraOptions, animationOptions);
+ self.mbglMap.easeTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"camera"];
}
@@ -3444,6 +3528,15 @@ public:
- (void)_flyToCamera:(MGLMapCamera *)camera edgePadding:(UIEdgeInsets)insets withDuration:(NSTimeInterval)duration peakAltitude:(CLLocationDistance)peakAltitude completionHandler:(nullable void (^)(void))completion
{
+ if (!_mbglMap)
+ {
+ if (completion)
+ {
+ completion();
+ }
+ return;
+ }
+
mbgl::AnimationOptions animationOptions;
if (duration >= 0)
{
@@ -3482,13 +3575,17 @@ public:
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:insets];
- _mbglMap->flyTo(cameraOptions, animationOptions);
+ self.mbglMap.flyTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"camera"];
}
- (void)cancelTransitions {
+ if (!_mbglMap)
+ {
+ return;
+ }
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonTransitionCancelled;
- _mbglMap->cancelTransitions();
+ self.mbglMap.cancelTransitions();
self.cameraChangeReasonBitmask &= ~MGLCameraChangeReasonTransitionCancelled;
}
@@ -3499,14 +3596,24 @@ public:
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets
{
+ if (!_mbglMap)
+ {
+ return nil;
+ }
+
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
- mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), padding);
+ mbgl::CameraOptions cameraOptions = self.mbglMap.cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), padding);
return [self cameraForCameraOptions:cameraOptions];
}
- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets
{
+ if (!_mbglMap)
+ {
+ return nil;
+ }
+
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
@@ -3514,11 +3621,16 @@ public:
CGFloat pitch = camera.pitch < 0 ? currentCamera.pitch : camera.pitch;
CLLocationDirection direction = camera.heading < 0 ? currentCamera.heading : camera.heading;
- mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), padding, direction, pitch);
+ mbgl::CameraOptions cameraOptions = self.mbglMap.cameraForLatLngBounds(MGLLatLngBoundsFromCoordinateBounds(bounds), padding, direction, pitch);
return [self cameraForCameraOptions:cameraOptions];
}
- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingShape:(MGLShape *)shape edgePadding:(UIEdgeInsets)insets {
+ if (!_mbglMap)
+ {
+ return nil;
+ }
+
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
@@ -3526,26 +3638,36 @@ public:
CGFloat pitch = camera.pitch < 0 ? currentCamera.pitch : camera.pitch;
CLLocationDirection direction = camera.heading < 0 ? currentCamera.heading : camera.heading;
- mbgl::CameraOptions cameraOptions = _mbglMap->cameraForGeometry([shape geometryObject], padding, direction, pitch);
+ mbgl::CameraOptions cameraOptions = self.mbglMap.cameraForGeometry([shape geometryObject], padding, direction, pitch);
return [self cameraForCameraOptions: cameraOptions];
}
- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape direction:(CLLocationDirection)direction edgePadding:(UIEdgeInsets)insets {
+ if (!_mbglMap)
+ {
+ return nil;
+ }
+
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
- mbgl::CameraOptions cameraOptions = _mbglMap->cameraForGeometry([shape geometryObject], padding, direction);
+ mbgl::CameraOptions cameraOptions = self.mbglMap.cameraForGeometry([shape geometryObject], padding, direction);
return [self cameraForCameraOptions:cameraOptions];
}
- (MGLMapCamera *)cameraForCameraOptions:(const mbgl::CameraOptions &)cameraOptions
{
- CLLocationCoordinate2D centerCoordinate = MGLLocationCoordinate2DFromLatLng(cameraOptions.center ? *cameraOptions.center : _mbglMap->getLatLng());
+ if (!_mbglMap)
+ {
+ return nil;
+ }
+
+ CLLocationCoordinate2D centerCoordinate = MGLLocationCoordinate2DFromLatLng(cameraOptions.center ? *cameraOptions.center : self.mbglMap.getLatLng());
double zoomLevel = cameraOptions.zoom ? *cameraOptions.zoom : self.zoomLevel;
CLLocationDirection direction = cameraOptions.angle ? mbgl::util::wrap(*cameraOptions.angle, 0., 360.) : self.direction;
- CGFloat pitch = cameraOptions.pitch ? *cameraOptions.pitch : _mbglMap->getPitch();
+ CGFloat pitch = cameraOptions.pitch ? *cameraOptions.pitch : self.mbglMap.getPitch();
CLLocationDistance altitude = MGLAltitudeForZoomLevel(zoomLevel, pitch, centerCoordinate.latitude, self.frame.size);
return [MGLMapCamera cameraLookingAtCenterCoordinate:centerCoordinate altitude:altitude pitch:pitch heading:direction];
}
@@ -3583,7 +3705,7 @@ public:
- (mbgl::LatLng)convertPoint:(CGPoint)point toLatLngFromView:(nullable UIView *)view
{
CGPoint convertedPoint = [self convertPoint:point fromView:view];
- return _mbglMap->latLngForPixel(mbgl::ScreenCoordinate(convertedPoint.x, convertedPoint.y)).wrapped();
+ return self.mbglMap.latLngForPixel(mbgl::ScreenCoordinate(convertedPoint.x, convertedPoint.y)).wrapped();
}
- (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(nullable UIView *)view
@@ -3598,7 +3720,7 @@ public:
/// Converts a geographic coordinate to a point in the view’s coordinate system.
- (CGPoint)convertLatLng:(mbgl::LatLng)latLng toPointToView:(nullable UIView *)view
{
- mbgl::ScreenCoordinate pixel = _mbglMap->pixelForLatLng(latLng);
+ mbgl::ScreenCoordinate pixel = self.mbglMap.pixelForLatLng(latLng);
return [self convertPoint:CGPointMake(pixel.x, pixel.y) toView:view];
}
@@ -3816,7 +3938,7 @@ public:
}
_isChangingAnnotationLayers = YES;
- MGLAnnotationTag annotationTag = _mbglMap->addAnnotation([multiPoint annotationObjectWithDelegate:self]);
+ MGLAnnotationTag annotationTag = self.mbglMap.addAnnotation([multiPoint annotationObjectWithDelegate:self]);
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
@@ -3884,7 +4006,7 @@ public:
annotationImagesForAnnotation[annotationValue] = annotationImage;
}
- MGLAnnotationTag annotationTag = _mbglMap->addAnnotation(mbgl::SymbolAnnotation {
+ MGLAnnotationTag annotationTag = self.mbglMap.addAnnotation(mbgl::SymbolAnnotation {
MGLPointFromLocationCoordinate2D(annotation.coordinate),
symbolName.UTF8String
});
@@ -4063,7 +4185,7 @@ public:
annotationImage.delegate = self;
// add sprite
- _mbglMap->addAnnotationImage([annotationImage.image mgl_styleImageWithIdentifier:iconIdentifier]);
+ self.mbglMap.addAnnotationImage([annotationImage.image mgl_styleImageWithIdentifier:iconIdentifier]);
// Create a slop area with a “radius” equal in size to the annotation
// image’s alignment rect, allowing the eventual tap to be on any point
@@ -4137,7 +4259,7 @@ public:
}
_isChangingAnnotationLayers = YES;
- _mbglMap->removeAnnotation(annotationTag);
+ self.mbglMap.removeAnnotation(annotationTag);
}
[self didChangeValueForKey:@"annotations"];
@@ -4889,7 +5011,7 @@ public:
if ([pair.second.imageReuseIdentifier isEqualToString:reuseIdentifier])
{
const mbgl::Point<double> point = MGLPointFromLocationCoordinate2D(pair.second.annotation.coordinate);
- _mbglMap->updateAnnotation(pair.first, mbgl::SymbolAnnotation { point, iconIdentifier.UTF8String ?: "" });
+ self.mbglMap.updateAnnotation(pair.first, mbgl::SymbolAnnotation { point, iconIdentifier.UTF8String ?: "" });
}
}
}
@@ -5610,7 +5732,7 @@ public:
- (CGFloat)currentMinimumZoom
{
- return fmaxf(_mbglMap->getMinZoom(), MGLMinimumZoom);
+ return fmaxf(self.mbglMap.getMinZoom(), MGLMinimumZoom);
}
- (BOOL)isRotationAllowed
@@ -5670,7 +5792,8 @@ public:
}
- (void)cameraWillChangeAnimated:(BOOL)animated {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5704,7 +5827,8 @@ public:
}
- (void)cameraIsChanging {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5722,7 +5846,8 @@ public:
}
- (void)cameraDidChangeAnimated:(BOOL)animated {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5768,7 +5893,8 @@ public:
}
- (void)mapViewWillStartLoadingMap {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5779,7 +5905,8 @@ public:
}
- (void)mapViewDidFinishLoadingMap {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5794,7 +5921,8 @@ public:
}
- (void)mapViewDidFailLoadingMapWithError:(NSError *)error {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5805,7 +5933,8 @@ public:
}
- (void)mapViewWillStartRenderingFrame {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5816,7 +5945,8 @@ public:
}
- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5833,7 +5963,8 @@ public:
}
- (void)mapViewWillStartRenderingMap {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5844,7 +5975,8 @@ public:
}
- (void)mapViewDidFinishRenderingMapFullyRendered:(BOOL)fullyRendered {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
@@ -5857,11 +5989,12 @@ public:
}
- (void)didFinishLoadingStyle {
- if (!_mbglMap) {
+ if (!_mbglMap)
+ {
return;
}
- self.style = [[MGLStyle alloc] initWithRawStyle:&_mbglMap->getStyle() mapView:self];
+ self.style = [[MGLStyle alloc] initWithRawStyle:&self.mbglMap.getStyle() mapView:self];
if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
{
[self.delegate mapView:self didFinishLoadingStyle:self.style];
@@ -6200,7 +6333,7 @@ public:
- (BOOL)isFullyLoaded
{
- return _mbglMap->isFullyLoaded();
+ return self.mbglMap.isFullyLoaded();
}
- (void)prepareForInterfaceBuilder