diff --git a/.gitignore b/.gitignore
index 69fc13925ef..f834afc948a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,10 @@
/cmake-build-debug
/platform/android/build
/platform/android/MapboxGLAndroidSDK/src/main/assets/sdk_versions/com.mapbox.mapboxsdk
+/platform/ios/platform/ios/Mapbox.playground/build/
*.code-workspace
+
+.DS_Store
/build
**/.idea
/platform/android/MapboxGLAndroidSDKTestApp/local.properties
diff --git a/.gitignore.swp b/.gitignore.swp
new file mode 100644
index 00000000000..19432fd5f18
Binary files /dev/null and b/.gitignore.swp differ
diff --git a/platform/ios/platform/ios/ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/platform/ios/platform/ios/ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000000..18d981003d6
--- /dev/null
+++ b/platform/ios/platform/ios/ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme b/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
index a1237e01589..0a934c8830d 100644
--- a/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
+++ b/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
@@ -1,6 +1,6 @@
@@ -31,7 +31,7 @@
@@ -54,7 +54,7 @@
@@ -78,7 +78,7 @@
diff --git a/platform/ios/platform/ios/src/MGLMapView.mm b/platform/ios/platform/ios/src/MGLMapView.mm
index c17ba1bec91..f54a9759801 100644
--- a/platform/ios/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/platform/ios/src/MGLMapView.mm
@@ -158,6 +158,12 @@ typedef NS_ENUM(NSUInteger, MGLUserTrackingState) {
/// The threshold used to consider when a tilt gesture should start.
const CLLocationDegrees MGLHorizontalTiltToleranceDegrees = 45.0;
+/// The time between background snapshot attempts.
+const NSTimeInterval MGLBackgroundSnapshotImageInterval = 60.0;
+
+/// The delay after the map has idled before a background snapshot is attempted.
+const NSTimeInterval MGLBackgroundSnapshotImageIdleDelay = 3.0;
+
/// Mapping from an annotation tag to metadata about that annotation, including
/// the annotation itself.
typedef std::unordered_map MGLAnnotationTagContextMap;
@@ -1552,23 +1558,27 @@ - (void)pauseRendering:(__unused NSNotification *)notification
_displayLink.paused = YES;
[self processPendingBlocks];
- if ( ! self.glSnapshotView)
+ if (self.lastSnapshotImage)
{
- self.glSnapshotView = [[UIImageView alloc] initWithFrame: _mbglView->getView().frame];
- self.glSnapshotView.autoresizingMask = _mbglView->getView().autoresizingMask;
- self.glSnapshotView.contentMode = UIViewContentModeCenter;
- [self insertSubview:self.glSnapshotView aboveSubview:_mbglView->getView()];
- }
-
- self.glSnapshotView.image = self.lastSnapshotImage;
- self.glSnapshotView.hidden = NO;
+ if ( ! self.glSnapshotView)
+ {
+ self.glSnapshotView = [[UIImageView alloc] initWithFrame: _mbglView->getView().frame];
+ self.glSnapshotView.autoresizingMask = _mbglView->getView().autoresizingMask;
+ self.glSnapshotView.contentMode = UIViewContentModeCenter;
+ [self insertSubview:self.glSnapshotView aboveSubview:_mbglView->getView()];
+ }
+
+ self.glSnapshotView.image = self.lastSnapshotImage;
+ self.glSnapshotView.hidden = NO;
+ self.glSnapshotView.alpha = 1;
- if (self.debugMask && [self.glSnapshotView.subviews count] == 0)
- {
- UIView *snapshotTint = [[UIView alloc] initWithFrame:self.glSnapshotView.bounds];
- snapshotTint.autoresizingMask = self.glSnapshotView.autoresizingMask;
- snapshotTint.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.25];
- [self.glSnapshotView addSubview:snapshotTint];
+ if (self.debugMask && [self.glSnapshotView.subviews count] == 0)
+ {
+ UIView *snapshotTint = [[UIView alloc] initWithFrame:self.glSnapshotView.bounds];
+ snapshotTint.autoresizingMask = self.glSnapshotView.autoresizingMask;
+ snapshotTint.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.25];
+ [self.glSnapshotView addSubview:snapshotTint];
+ }
}
_mbglView->deleteView();
@@ -1586,9 +1596,15 @@ - (void)resumeRendering:(__unused NSNotification *)notification
_mbglView->createView();
- self.glSnapshotView.hidden = YES;
-
- [self.glSnapshotView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
+ [UIView transitionWithView:self
+ duration:0.25
+ options:UIViewAnimationOptionTransitionCrossDissolve
+ animations:^{
+ self.glSnapshotView.hidden = YES;
+ }
+ completion:^(BOOL finished) {
+ [self.glSnapshotView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
+ }];
_displayLink.paused = NO;
@@ -5946,29 +5962,32 @@ - (void)dismissHeadingCalibrationDisplay:(id)manager
- (void)locationManager:(__unused id)manager didUpdateHeading:(CLHeading *)newHeading
{
- if ( ! _showsUserLocation || self.pan.state == UIGestureRecognizerStateBegan || newHeading.headingAccuracy < 0) return;
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
+ if ( ! self->_showsUserLocation || self.pan.state == UIGestureRecognizerStateBegan || newHeading.headingAccuracy < 0) return;
- self.userLocation.heading = newHeading;
+ self.userLocation.heading = newHeading;
- if (self.showsUserHeadingIndicator || self.userTrackingMode == MGLUserTrackingModeFollowWithHeading)
- {
- [self updateUserLocationAnnotationView];
- }
+ if (self.showsUserHeadingIndicator || self.userTrackingMode == MGLUserTrackingModeFollowWithHeading)
+ {
+ [self updateUserLocationAnnotationView];
+ }
- if ([self.delegate respondsToSelector:@selector(mapView:didUpdateUserLocation:)])
- {
- [self.delegate mapView:self didUpdateUserLocation:self.userLocation];
+ if ([self.delegate respondsToSelector:@selector(mapView:didUpdateUserLocation:)])
+ {
+ [self.delegate mapView:self didUpdateUserLocation:self.userLocation];
- if ( ! _showsUserLocation) return;
- }
+ if (!self->_showsUserLocation) return;
+ }
- CLLocationDirection headingDirection = (newHeading.trueHeading >= 0 ? newHeading.trueHeading : newHeading.magneticHeading);
+ CLLocationDirection headingDirection = (newHeading.trueHeading >= 0 ? newHeading.trueHeading : newHeading.magneticHeading);
- if (headingDirection >= 0 && self.userTrackingMode == MGLUserTrackingModeFollowWithHeading
- && self.userTrackingState != MGLUserTrackingStateBegan)
- {
- [self _setDirection:headingDirection animated:YES];
- }
+ if (headingDirection >= 0 && self.userTrackingMode == MGLUserTrackingModeFollowWithHeading
+ && self.userTrackingState != MGLUserTrackingStateBegan)
+ {
+ [self _setDirection:headingDirection animated:YES];
+ [self updateUserLocationAnnotationView];
+ }
+ });
}
- (void)locationManager:(__unused id)manager didFailWithError:(NSError *)error
@@ -6353,6 +6372,8 @@ - (void)mapViewDidFailLoadingMapWithError:(NSError *)error {
}
- (void)mapViewWillStartRenderingFrame {
+ [self cancelBackgroundSnapshot];
+
if (!_mbglMap)
{
return;
@@ -6412,7 +6433,9 @@ - (void)mapViewDidBecomeIdle {
if (!_mbglMap) {
return;
}
-
+
+ [self queueBackgroundSnapshot];
+
if ([self.delegate respondsToSelector:@selector(mapViewDidBecomeIdle:)]) {
[self.delegate mapViewDidBecomeIdle:self];
}
@@ -6891,6 +6914,39 @@ - (void)prepareForInterfaceBuilder
return _annotationViewReuseQueueByIdentifier[identifier];
}
+#pragma mark - Snapshot image -
+
+- (void)attemptBackgroundSnapshot {
+ static NSTimeInterval lastSnapshotTime = 0.0;
+
+ if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
+ return;
+ }
+
+ NSTimeInterval now = CACurrentMediaTime();
+
+ if (lastSnapshotTime == 0.0 || (now - lastSnapshotTime > MGLBackgroundSnapshotImageInterval)) {
+ self.lastSnapshotImage = _mbglView->snapshot();
+ lastSnapshotTime = now;
+ }
+}
+
+- (void)cancelBackgroundSnapshot
+{
+ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(attemptBackgroundSnapshot) object:nil];
+}
+
+- (void)queueBackgroundSnapshot {
+ if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
+ return;
+ }
+
+ [self cancelBackgroundSnapshot];
+ [self performSelector:@selector(attemptBackgroundSnapshot)
+ withObject:nil
+ afterDelay:MGLBackgroundSnapshotImageIdleDelay];
+}
+
@end
#pragma mark - IBAdditions methods