diff options
Diffstat (limited to 'platform/ios/src')
-rw-r--r-- | platform/ios/src/MGLAccountManager.m | 10 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 114 |
2 files changed, 87 insertions, 37 deletions
diff --git a/platform/ios/src/MGLAccountManager.m b/platform/ios/src/MGLAccountManager.m index 764f9f097b..6b98d5286a 100644 --- a/platform/ios/src/MGLAccountManager.m +++ b/platform/ios/src/MGLAccountManager.m @@ -1,7 +1,9 @@ #import "MGLAccountManager_Private.h" #import "MGLMapboxEvents.h" +#import "MGLMapView.h" #import "NSBundle+MGLAdditions.h" #import "NSProcessInfo+MGLAdditions.h" +#import "NSString+MGLAdditions.h" #import "FABKitProtocol.h" #import "Fabric+FABKits.h" @@ -93,6 +95,14 @@ } else { NSLog(@"MGLAccountManager is used in a project that doesn't have Fabric."); } + + // https://github.com/mapbox/mapbox-gl-native/issues/2966 + mgl_linkBundleCategory(); + mgl_linkStringCategory(); + mgl_linkProcessInfoCategory(); + + // https://github.com/mapbox/mapbox-gl-native/issues/3113 + [MGLMapView class]; } @end diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 4f732fb627..78ab235332 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -147,6 +147,7 @@ public: GLKViewDelegate, CLLocationManagerDelegate, UIActionSheetDelegate, + SMCalloutViewDelegate, MGLCalloutViewDelegate, UIAlertViewDelegate, MGLMultiPointDelegate, @@ -313,7 +314,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) _mbglFileSource = new mbgl::DefaultFileSource([fileCachePath UTF8String], [[[[NSBundle mainBundle] resourceURL] path] UTF8String]); // setup mbgl map - _mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous); + _mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None); // start paused if in IB if (_isTargetingInterfaceBuilder || background) { @@ -759,7 +760,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) // This is the delegate of the GLKView object's display call. - (void)glkView:(__unused GLKView *)view drawInRect:(__unused CGRect)rect { - if ( ! self.isDormant) + if ( ! self.dormant) { CGFloat zoomFactor = _mbglMap->getMaxZoom() - _mbglMap->getMinZoom() + 1; CGFloat cpuFactor = (CGFloat)[[NSProcessInfo processInfo] processorCount]; @@ -905,7 +906,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) { MGLAssertIsMainThread(); - if ( ! self.isDormant) + if ( ! self.dormant) { [self validateDisplayLink]; self.dormant = YES; @@ -919,6 +920,11 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) BOOL isVisible = self.superview && self.window; if (isVisible && ! _displayLink) { + if (_mbglMap->getConstrainMode() == mbgl::ConstrainMode::None) + { + _mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly); + } + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateFromDisplayLink)]; _displayLink.frameInterval = MGLTargetFrameInterval; [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; @@ -951,6 +957,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) { self.dormant = YES; + [self validateLocationServices]; + [MGLMapboxEvents flush]; _displayLink.paused = YES; @@ -1000,6 +1008,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) _mbglMap->resume(); _displayLink.paused = NO; + + [self validateLocationServices]; } } @@ -1482,6 +1492,14 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) return [self.delegate respondsToSelector:@selector(mapView:tapOnCalloutForAnnotation:)]; } +- (void)calloutViewClicked:(__unused SMCalloutView *)calloutView +{ + if ([self.delegate respondsToSelector:@selector(mapView:tapOnCalloutForAnnotation:)]) + { + [self.delegate mapView:self tapOnCalloutForAnnotation:self.selectedAnnotation]; + } +} + - (void)calloutViewTapped:(__unused MGLCompactCalloutView *)calloutView { if ([self.delegate respondsToSelector:@selector(mapView:tapOnCalloutForAnnotation:)]) @@ -2643,7 +2661,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) // Filter out any annotation whose image is unselectable or for which // hit testing fails. - std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag annotationTag) + auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), + [&](const MGLAnnotationTag annotationTag) { id <MGLAnnotation> annotation = [self annotationWithTag:annotationTag]; NSAssert(annotation, @"Unknown annotation found nearby tap"); @@ -2660,6 +2679,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) centeredAtCoordinate:annotation.coordinate]; return !!!CGRectIntersectsRect(annotationRect, hitRect); }); + nearbyAnnotations.resize(std::distance(nearbyAnnotations.begin(), end)); } MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound; @@ -2689,19 +2709,28 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) if (_selectedAnnotationTag == MGLAnnotationTagNotFound || _selectedAnnotationTag == _annotationsNearbyLastTap.back()) { - // Either an annotation from this set hasn’t been selected - // before or the last annotation in the set was selected. Wrap - // around to the first annotation in the set. + // Either no annotation is selected or the last annotation in + // the set was selected. Wrap around to the first annotation in + // the set. hitAnnotationTag = _annotationsNearbyLastTap.front(); } else { - // Step to the next annotation in the set. auto result = std::find(_annotationsNearbyLastTap.begin(), _annotationsNearbyLastTap.end(), _selectedAnnotationTag); - auto distance = std::distance(_annotationsNearbyLastTap.begin(), result); - hitAnnotationTag = _annotationsNearbyLastTap[distance + 1]; + if (result == _annotationsNearbyLastTap.end()) + { + // An annotation from this set hasn’t been selected before. + // Select the first (nearest) one. + hitAnnotationTag = _annotationsNearbyLastTap.front(); + } + else + { + // Step to the next annotation in the set. + auto distance = std::distance(_annotationsNearbyLastTap.begin(), result); + hitAnnotationTag = _annotationsNearbyLastTap[distance + 1]; + } } } else @@ -2997,45 +3026,31 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) #pragma mark - User Location - -- (void)setShowsUserLocation:(BOOL)showsUserLocation +- (void)validateLocationServices { - if (showsUserLocation == _showsUserLocation || _isTargetingInterfaceBuilder) return; - - _showsUserLocation = showsUserLocation; + BOOL shouldEnableLocationServices = self.showsUserLocation && !self.dormant; - if (showsUserLocation) + if (shouldEnableLocationServices && ! self.locationManager) { - if ([self.delegate respondsToSelector:@selector(mapViewWillStartLocatingUser:)]) - { - [self.delegate mapViewWillStartLocatingUser:self]; - } - - self.userLocationAnnotationView = [[MGLUserLocationAnnotationView alloc] initInMapView:self]; - self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | - UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); - - self.locationManager = [CLLocationManager new]; + self.locationManager = [[CLLocationManager alloc] init]; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - // enable iOS 8+ location authorization API - // - if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) + if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) { - BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] || - [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]; + BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] || [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]; if (!hasLocationDescription) { [NSException raise:@"Missing Location Services usage description" format: - @"In iOS 8 and above, this app must have a value for NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in its Info.plist."]; + @"In iOS 8 and above, this app must have a value for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription in its Info.plist."]; } - // request location permissions, if both keys exist ask for less permissive - if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) + + if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) { - [self.locationManager requestWhenInUseAuthorization]; + [self.locationManager requestAlwaysAuthorization]; } - else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) + else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) { - [self.locationManager requestAlwaysAuthorization]; + [self.locationManager requestWhenInUseAuthorization]; } } #endif @@ -3044,12 +3059,37 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) self.locationManager.delegate = self; [self.locationManager startUpdatingLocation]; } - else + else if ( ! shouldEnableLocationServices && self.locationManager) { [self.locationManager stopUpdatingLocation]; [self.locationManager stopUpdatingHeading]; self.locationManager.delegate = nil; self.locationManager = nil; + } +} + +- (void)setShowsUserLocation:(BOOL)showsUserLocation +{ + if (showsUserLocation == _showsUserLocation || _isTargetingInterfaceBuilder) return; + + _showsUserLocation = showsUserLocation; + + if (showsUserLocation) + { + if ([self.delegate respondsToSelector:@selector(mapViewWillStartLocatingUser:)]) + { + [self.delegate mapViewWillStartLocatingUser:self]; + } + + self.userLocationAnnotationView = [[MGLUserLocationAnnotationView alloc] initInMapView:self]; + self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | + UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); + + [self validateLocationServices]; + } + else + { + [self validateLocationServices]; if ([self.delegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)]) { |