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

Commit

Permalink
[ios] Refactor MGLMapView's location services
Browse files Browse the repository at this point in the history
- Pause location services when the app goes to sleep; address iOS 8 blue bar issue.
- Only ask for location permissions if not already granted/denied.
- Cleanup usage of `.isDormant` → `.dormant`

Partially addresses #2945, for which a full and complete fix waits until #4030.
  • Loading branch information
friedbunny committed Feb 19, 2016
1 parent 9f4e8dd commit 15b9f31
Showing 1 changed file with 44 additions and 29 deletions.
73 changes: 44 additions & 29 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ - (void)setOpaque:(BOOL)opaque
// 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];
Expand Down Expand Up @@ -906,7 +906,7 @@ - (void)willTerminate
{
MGLAssertIsMainThread();

if ( ! self.isDormant)
if ( ! self.dormant)
{
[self validateDisplayLink];
self.dormant = YES;
Expand Down Expand Up @@ -957,6 +957,8 @@ - (void)sleepGL:(__unused NSNotification *)notification
{
self.dormant = YES;

[self validateLocationServices];

[MGLMapboxEvents flush];

_displayLink.paused = YES;
Expand Down Expand Up @@ -1006,6 +1008,8 @@ - (void)wakeGL:(__unused NSNotification *)notification
_mbglMap->resume();

_displayLink.paused = NO;

[self validateLocationServices];
}
}

Expand Down Expand Up @@ -3022,45 +3026,31 @@ - (void)annotationImageNeedsRedisplay:(MGLAnnotationImage *)annotationImage

#pragma mark - User Location -

- (void)setShowsUserLocation:(BOOL)showsUserLocation
- (void)validateLocationServices
{
if (showsUserLocation == _showsUserLocation || _isTargetingInterfaceBuilder) return;
BOOL shouldEnableLocationServices = self.showsUserLocation && !self.dormant;

_showsUserLocation = showsUserLocation;

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
Expand All @@ -3069,12 +3059,37 @@ - (void)setShowsUserLocation:(BOOL)showsUserLocation
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:)])
{
Expand Down

0 comments on commit 15b9f31

Please sign in to comment.