summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Rex <julian.rex@gmail.com>2018-11-20 14:31:09 -0500
committerGitHub <noreply@github.com>2018-11-20 14:31:09 -0500
commit53bbf9d6991c1eddfa141ddcfb4b7252874e46ec (patch)
tree3ad8c97d579c4086b3682e27e6ff3deae52680f6
parent8b232f693dc3f835bbb91c6c4bdf07020e98c164 (diff)
downloadqtlocation-mapboxgl-53bbf9d6991c1eddfa141ddcfb4b7252874e46ec.tar.gz
[ios] Added teardown of core objects when receiving UIApplicationWillTerminateNotification (#13367)
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.h4
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.mm46
-rw-r--r--platform/ios/CHANGELOG.md1
-rw-r--r--platform/ios/app/MBXViewController.m2
-rw-r--r--platform/ios/src/MGLMapView.h34
-rw-r--r--platform/ios/src/MGLMapView.mm329
-rw-r--r--platform/ios/src/MGLMapView_Private.h5
7 files changed, 317 insertions, 104 deletions
diff --git a/platform/darwin/src/MGLMapSnapshotter.h b/platform/darwin/src/MGLMapSnapshotter.h
index de509f73f4..2bd9d99fe0 100644
--- a/platform/darwin/src/MGLMapSnapshotter.h
+++ b/platform/darwin/src/MGLMapSnapshotter.h
@@ -173,6 +173,8 @@ typedef void (^MGLMapSnapshotCompletionHandler)(MGLMapSnapshot* _Nullable snapsh
MGL_EXPORT
@interface MGLMapSnapshotter : NSObject
+- (instancetype)init NS_UNAVAILABLE;
+
/**
Initializes and returns a map snapshotter object that produces snapshots
according to the given options.
@@ -180,7 +182,7 @@ MGL_EXPORT
@param options The options to use when generating a map snapshot.
@return An initialized map snapshotter.
*/
-- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options;
+- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options NS_DESIGNATED_INITIALIZER;
/**
Starts the snapshot creation and executes the specified block with the result.
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm
index 3c5e36f8f2..639a3b62ee 100644
--- a/platform/darwin/src/MGLMapSnapshotter.mm
+++ b/platform/darwin/src/MGLMapSnapshotter.mm
@@ -117,6 +117,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
@interface MGLMapSnapshotter()
@property (nonatomic) BOOL cancelled;
+@property (nonatomic) BOOL terminated;
@property (nonatomic) dispatch_queue_t resultQueue;
@property (nonatomic, copy) MGLMapSnapshotCompletionHandler completion;
+ (void)completeWithErrorCode:(MGLErrorCode)errorCode description:(nonnull NSString*)description onQueue:(dispatch_queue_t)queue completion:(MGLMapSnapshotCompletionHandler)completion;
@@ -129,6 +130,8 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
}
- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
if (_completion) {
MGLAssert(_snapshotCallback, @"Snapshot in progress - there should be a valid callback");
@@ -139,16 +142,41 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
}
}
+
+- (instancetype)init {
+ NSAssert(NO, @"Please use -[MGLMapSnapshotter initWithOptions:]");
+ [super doesNotRecognizeSelector:_cmd];
+ return nil;
+}
+
- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options
{
MGLLogDebug(@"Initializing withOptions: %@", options);
self = [super init];
if (self) {
[self setOptions:options];
+#if TARGET_OS_IPHONE
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
+#else
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:NSApplicationWillTerminateNotification object:nil];
+#endif
}
return self;
}
+- (void)applicationWillTerminate:(NSNotification *)notification
+{
+ if (self.completion) {
+ [self cancel];
+ }
+
+ _mbglMapSnapshotter.reset();
+ _snapshotCallback.reset();
+ _mbglThreadPool.reset();
+
+ self.terminated = YES;
+}
+
- (void)startWithCompletionHandler:(MGLMapSnapshotCompletionHandler)completion
{
MGLLogDebug(@"Starting withCompletionHandler: %@", completion);
@@ -167,7 +195,12 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[NSException raise:NSInternalInconsistencyException
format:@"Already started this snapshotter."];
}
-
+
+ if (self.terminated) {
+ [NSException raise:NSInternalInconsistencyException
+ format:@"Starting a snapshotter after application termination is not supported."];
+ }
+
self.completion = completion;
self.resultQueue = queue;
self.cancelled = NO;
@@ -539,7 +572,18 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
- (void)setOptions:(MGLMapSnapshotOptions *)options
{
+ if (_terminated) {
+ [NSException raise:NSInternalInconsistencyException
+ format:@"Calling MGLMapSnapshotter.options after application termination is not supported."];
+ }
+
MGLLogDebug(@"Setting options: %@", options);
+
+ if (_completion) {
+ [self cancel];
+ }
+
+ _cancelled = NO;
_options = options;
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
_mbglThreadPool = mbgl::sharedThreadPool();
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index 2352879dae..a93555ebe8 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -9,6 +9,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Added `MGLLoggingConfiguration` and `MGLLoggingBlockHandler` that handle error and fault events produced by the SDK. ([#13235](https://github.com/mapbox/mapbox-gl-native/pull/13235))
* This SDK’s dynamic framework now has a bundle identifier of `com.mapbox.Mapbox`. ([#12857](https://github.com/mapbox/mapbox-gl-native/pull/12857))
* Modified the behavior of the map view so that programmatic camera transitions can no longer be interrupted by user interaction when `MGLMapView.zoomEnabled`, `MGLMapView.rotateEnabled`, `MGLMapView.scrollEnabled`, and `MGLMapView.pitchEnabled` are set to false. ([#13362](https://github.com/mapbox/mapbox-gl-native/pull/13362))
+* Fixed random crashes during app termination. ([#13367](https://github.com/mapbox/mapbox-gl-native/pull/13367))
* Added `-[MGLStyle removeSource:error:]` that returns a `BOOL` indicating success (and an optional `NSError` in case of failure). ([#13399](https://github.com/mapbox/mapbox-gl-native/pull/13399))
## 4.6.0 - November 7, 2018
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 3520051434..f058b75dc9 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -1986,7 +1986,7 @@ CLLocationCoordinate2D randomWorldCoordinate() {
annotationView.backgroundColor = [UIColor whiteColor];
// Note that having two long press gesture recognizers on overlapping
- // views (`self.view` & `annotationView`) will cause weird behaviour.
+ // views (`self.view` & `annotationView`) will cause weird behavior.
// Comment out the pin dropping functionality in the handleLongPress:
// method in this class to make draggable annotation views play nice.
annotationView.draggable = YES;
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h
index 0f8de86555..fd433fe1b3 100644
--- a/platform/ios/src/MGLMapView.h
+++ b/platform/ios/src/MGLMapView.h
@@ -636,11 +636,14 @@ MGL_EXPORT IB_DESIGNABLE
Changing the center coordinate centers the map on the new coordinate without
changing the current zoom level.
-
+
@param coordinate The new center coordinate for the map.
@param animated Specify `YES` if you want the map view to scroll to the new
location or `NO` if you want the map to display the new location
immediately.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`.
*/
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
@@ -653,6 +656,9 @@ MGL_EXPORT IB_DESIGNABLE
@param animated Specify `YES` if you want the map view to animate scrolling and
zooming to the new location or `NO` if you want the map to display the new
location immediately.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`.
*/
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel animated:(BOOL)animated;
@@ -667,6 +673,9 @@ MGL_EXPORT IB_DESIGNABLE
@param animated Specify `YES` if you want the map view to animate scrolling,
zooming, and rotating to the new location or `NO` if you want the map to
display the new location immediately.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`.
*/
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated;
@@ -682,6 +691,9 @@ MGL_EXPORT IB_DESIGNABLE
zooming, and rotating to the new location or `NO` if you want the map to
display the new location immediately.
@param completion The block executed after the animation finishes.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`.
*/
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion;
@@ -1020,6 +1032,10 @@ MGL_EXPORT IB_DESIGNABLE
bounds with zoom level as high (close to the ground) as possible while still
including the entire coordinate bounds. The camera object uses the current
direction and pitch.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`; you may receive a `nil` return value
+ depending on the order of notification delivery.
*/
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds;
@@ -1034,6 +1050,10 @@ MGL_EXPORT IB_DESIGNABLE
with zoom level as high (close to the ground) as possible while still
including the entire coordinate bounds. The camera object uses the current
direction and pitch.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`; you may receive a `nil` return value
+ depending on the order of notification delivery.
*/
- (MGLMapCamera *)cameraThatFitsCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets;
@@ -1050,6 +1070,10 @@ MGL_EXPORT IB_DESIGNABLE
with zoom level as high (close to the ground) as possible while still
including the entire coordinate bounds. The initial camera's pitch and
direction will be honored.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`; you may receive a `nil` return value
+ depending on the order of notification delivery.
*/
- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)insets;
@@ -1065,6 +1089,10 @@ MGL_EXPORT IB_DESIGNABLE
@return A camera object centered on the shape's center with zoom level as high
(close to the ground) as possible while still including the entire shape. The
initial camera's pitch and direction will be honored.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`; you may receive a `nil` return value
+ depending on the order of notification delivery.
*/
- (MGLMapCamera *)camera:(MGLMapCamera *)camera fittingShape:(MGLShape *)shape edgePadding:(UIEdgeInsets)insets;
@@ -1079,6 +1107,10 @@ MGL_EXPORT IB_DESIGNABLE
@return A camera object centered on the shape's center with zoom level as high
(close to the ground) as possible while still including the entire shape. The
camera object uses the current pitch.
+
+ @note The behavior of this method is undefined if called in response to
+ `UIApplicationWillTerminateNotification`; you may receive a `nil` return value
+ depending on the order of notification delivery.
*/
- (MGLMapCamera *)cameraThatFitsShape:(MGLShape *)shape direction:(CLLocationDirection)direction edgePadding:(UIEdgeInsets)insets;
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
diff --git a/platform/ios/src/MGLMapView_Private.h b/platform/ios/src/MGLMapView_Private.h
index 133d17023e..bddb9b093e 100644
--- a/platform/ios/src/MGLMapView_Private.h
+++ b/platform/ios/src/MGLMapView_Private.h
@@ -8,6 +8,9 @@ namespace mbgl {
/// Minimum size of an annotation’s accessibility element.
FOUNDATION_EXTERN const CGSize MGLAnnotationAccessibilityElementMinimumSize;
+/// Indicates that a method (that uses `mbgl::Map`) was called after app termination.
+FOUNDATION_EXTERN MGL_EXPORT MGLExceptionName const MGLUnderlyingMapUnavailableException;
+
@interface MGLMapView (Private)
/// Currently shown popover representing the selected annotation.
@@ -16,8 +19,6 @@ FOUNDATION_EXTERN const CGSize MGLAnnotationAccessibilityElementMinimumSize;
/** Triggers another render pass even when it is not necessary. */
- (void)setNeedsGLDisplay;
-- (mbgl::Map *)mbglMap;
-
- (mbgl::Renderer *)renderer;
/** Returns whether the map view is currently loading or processing any assets required to render the map */