Screen Shot 2014-09-23 at 09.40.05

“I’ve upgraded to iOS 8 and when testing my app I no longer receive location updates anymore”

This is what happened to all the apps that uses CoreLocation or/and MapKit or any other service that uses “Location Services” when upgrading from iOS 7 to iOS 8. Basically Apple has changed the “authorization pattern” and now developers have the responsibility to manually request for permissions to access location services.

Previous Behavior

Prior to iOS 8, when using CoreLocation, MapKit or any other service that requires location services, the system automatically detected the grant status for the app and displayed an alert in case the user has not “granted or not granted” yet access.  Also, once the user has granted/not granted access, the permission status could have simple values:

  • kCLAuthorizationStatusAuthorized
    The app can use location services as the user has granted access.
  • kCLAuthorizationStatusDenied
    The app can not use location services as the user has not granted access.

iOS 8 Approach

Starting from iOS 8, there are two new states of granted access to core location in replacement of the old kCLAuthorizationStatusAuthorized, which has been deprecated in iOS 8:

  • kCLAuthorizationStatusAuthorizedAlways
    The app can use the location services both in foreground and background, as well as monitor regions and significant location changes.
  • kCLAuthorizationStatusAuthorizedWhenInUse
    The app can use location services only and exclusively when being in foreground. This authorization does not allow you to use APIs that could launch your app in response to an event, such as region monitoring and the significant location change services.

Then, the developer needs to request for a specific authorization level manually, otherwise the user won’t be able to accept/deny it (the alert won’t be displayed) and the authorization status will be keep being kCLAuthorizationStatusNotDetermined, making impossible to access location services. In order to apply for this authorization we need to use one of the two following methods on CLLocationManager:

  • requestAlwaysAuthorization
    To request kCLAuthorizationStatusAuthorizedAlways access level.
  • requestWhenInUseAuthorization
    To request kCLAuthorizationStatusAuthorizedWhenInUse access level.

In addition, we need to provide (it is required) a description of “why the app want to use location services” in the info.plist by using the following keys and providing an string with the reason:

  • NSLocationAlwaysUsageDescription
  • NSLocationWhenInUseUsageDescription

Implementation Example

In our example, lets add support for location services access “when in use”, as our fake app needs just to track location in foreground.

1. First, lets add the keys in info.plist:

2. If planning to support compatibility with iOS 7  or lower together with iOS 8, it will be required some extra code to manage this calls that partially supported only in some versions of iOS. A good approach to do it is by checking the version of the system and using an if/else statement perform the calls or not.

Another approach is to ask the CLLocationManager if it responds to the selector requestWhenInUseAuthorization:

Caution: In case you don’t use CoreLocation directly but instead only MapKit and you want to display the user’s location, you will have to request access in any case, otherwise MapKit won’t be able to get the user’s location. Therefore, just create a CLLocationManager instance and request for the desired authorization level.

Joan Martin

Joan Martin

Starting with a mathematics degree, continuing with a computer science master's degree and working on mobile and backend development during the past 10 years, Joan is a proficient software engineer. Motivated by great projects and an awesome team, Joan is currently leading the engineering team at Mobile Jazz and enjoying the MJ philosophy at its best.