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

Commit

Permalink
[ios] Added teardown of core objects when receiving UIApplicationWill…
Browse files Browse the repository at this point in the history
…TerminateNotification (#13367)
  • Loading branch information
julianrex authored Nov 20, 2018
1 parent 8b232f6 commit 53bbf9d
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 104 deletions.
4 changes: 3 additions & 1 deletion platform/darwin/src/MGLMapSnapshotter.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,16 @@ 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.
@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.
Expand Down
46 changes: 45 additions & 1 deletion platform/darwin/src/MGLMapSnapshotter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ - (CLLocationCoordinate2D)coordinateForPoint:(NSPoint)point

@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;
Expand All @@ -129,6 +130,8 @@ @implementation MGLMapSnapshotter {
}

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];

if (_completion) {
MGLAssert(_snapshotCallback, @"Snapshot in progress - there should be a valid callback");

Expand All @@ -139,16 +142,41 @@ - (void)dealloc {
}
}


- (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);
Expand All @@ -167,7 +195,12 @@ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshot
[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;
Expand Down Expand Up @@ -539,7 +572,18 @@ + (void)completeWithErrorCode:(MGLErrorCode)errorCode description:(nonnull NSStr

- (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();
Expand Down
1 change: 1 addition & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion platform/ios/app/MBXViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1986,7 +1986,7 @@ - (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAn
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;
Expand Down
34 changes: 33 additions & 1 deletion platform/ios/src/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand All @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand All @@ -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;

Expand All @@ -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;

Expand All @@ -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;

Expand Down
Loading

0 comments on commit 53bbf9d

Please sign in to comment.