iOS 8 Location Services PSA

When Apple announced their changes to Location Services in iOS 8 at WWDC this year, a couple of things jumped out as being potentially problematic for developers (as well as users). I wrote about the changes in-depth on iMore back in June, but now that iOS 8 is out, and the changes are causing some confusion for people, I think it’s time to revisit them and discuss possible problems.

There are now two types of permission you can ask for with Location Services: Always and When In Use. I won’t go over which each one means here, but refer to the screenshot from WWDC below for a quick guide on which type your app will need. Any apps built for iOS 7 will default to asking for Always permission when run on iOS 8. This means your users will see a new, scary alert telling them that your app is monitoring their location even when they’re not using it. It also means even after a user has said yes, iOS will ask them again after a few days if they want to continue to allow your app to access their location even when not in use. For some apps this is fine. For others, users will panic and disable the permission. For this reason it’s important to push an update to properly handle Location Service permission on iOS 8. It’s also a healthy reminder to ensure your app will fail gracefully when users deny your app access to their location.

iOS 8 Location Services Matrix

The other important thing for developers to understand is the new requirements for prompting users for their location. If you don’t do this correctly, users will not get prompted to allow Location Services. I’ve seen and heard of a number of developers spinning their wheels when they run into this. It’s insidious because your user will not see any indication that something didn’t work, and Xcode doesn’t do a great job of telling developers when they’ve screwed this up. You are now required to define Location Services description strings in your Info.plist. If you request permission for Location Services and don’t have this set up properly, iOS won’t even bother prompting users.

Maps asking for permission in iOS 8

The two keys to concern yourself with are NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription. The values of these keys are the text that iOS will present to users in the Location Services alert when it prompts a user to give your app access. This is where you need to succinctly explain to your users why you need to know their location. If you only define one of these, but your app asks for the other type of permission, iOS won’t prompt the user.

Xcode Info.plist

You’ll also need to update your code to call requestAlwaysAuthorization or requestWhenInUseAuthorization when you want to ask the user for permission before attempting to call startUpdatingLocation.

Also be mindful of any third-party SDKs you’re using that might request Location Services before you do. Your app gets one chance to ask a user for permission. If your app only needs WhenInUse permission, but a third-party library is still rocking some iOS 7 code and it asks before you do, your app will request Always permission and if the user says no, you’re hosed.

I’ve also encountered third-party libraries that rely on which description string you’ve defined to infer which permission it should ask for. The problem with this is if you define both strings, there’s no way to know which string the library will key off of. In this case, you would only want to define the string of the permission type you intend to use. This should be fine, but if your app, or one of its libraries, ever asks for the permission that you haven’t defined a string for, we’re back to iOS never prompting the user. If you’re seeing your app fail to request permission, in all likelihood, you’re attempting to request a Location Services permission that you don’t have a description string for.

One last note: it appears if you compile with Xcode 5, you can still get away with not defining description strings, but obviously you don’t want to lean on that. I only mention it here because it’s still possible to ship an app for iOS 8 that will work fine without usage description strings, but this will likely come back to bite you later. Even if your code works now, make sure you’re doing things right so you and your users aren’t surprised later when your stuff breaks.

Finally, if you have trouble with apps from other developers not asking for Location Services when they need it because they’ve encountered one of the problems above, you can go to Settings > Privacy > Location Services and give the app permission there. The app will show up in the list, and when you tap on it you’ll see “Never” and either “Always” or “While Using the App” as your two choices. Enabling Location Services here will give the app the same permission as if it had correctly prompted you in the first place.

For more information, or clarification on anything I got wrong, see Apple’s CLLocationManager documentation.

3 comments

  1. Florent Pillet

    Nice post, thanks!

    One bug I noticed is that iOS 8 doesn’t use the localized InfoPlist.strings to localize the displayed message. It pulls it raw from Info.plist, unfortunately.

  2. Andy B

    Another issue I ran into: You can’t prompt the user to enable Always permissions if they previously accepted WhenInUse. Your only option is to direct users to permissions settings. I’m really hoping Apple fixes this in future updates, since it seems like a common use case.

Post a comment

You may use the following HTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>