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