Location Permission in iOS 13

How to request properly “Always Allow” permission

Quang NGO
The Startup
4 min readMay 15, 2020

--

In iOS 13, Apple made a big changes in location permission’s behaviour, especially for “Always Allow” permission. As I have been working full time on a location tracking app since 3 years, I encountered a big challenge and learned a lot from it when supporting iOS 13. In this story, I would like to share my experience when dealing with “Always Allow” request, and how iOS 13.4 brought a big improvement for user experience (though it looks like a workaround) to this request.

Note: I assume that audience knows implementing CoreLocation’s permission and functionality. In this story, I discuss only behaviour aspect, this is not a coding tutorial.

Summary of permission’s behaviour

In the code, developers can request two types of permission: “When in use” (requestWhenInUseAuthorization) and “Always Allow” (requestAlwaysAuthorization). In iOS 13, whichever option we use, we get this system popup:

This popup uses NSLocationWhenInUseUsageDescription string in the message. As you can see, even you request for “Always Allow”, this option is not available to choose anymore.

If user selects “Don’t Allow”, in the app and in the iOS Setting, we get .denied permission. This is a straightforward case to handle.

If user selects “Allow Once”, in the app we received .authorizedWhenInUse permission, and “Ask next time” in the iOS Setting. This option is new in iOS 13, and it replace the “Always Allow” option. If user selects this option, when restarting the app, both in app’s and iOS Setting’s permission status change back to .notDeterminated so we can request again the location permission.

If user selects “Allow While Using App”, well, this is the confusing part since the behaviour is different between requesting “When in Use” and “Always Allow”, and between iOS versions.

In case app requests “When in Use”, this choice “Allow While Using App” gives both app and system setting the .authorizedWhenInUse permission. It’s good since app get what it’s supposed to get.

In case app requests “Always Allow”, this choice “Allow While Using App” gives app .authorizedAlways and system setting .authorizedWhenInUse.

authorizedWhenInUse in app ; authorizedWhenInUse in setting (source: WWDC 2019)

You may ask “Why are they different? Is it a bug?”. Well, you’re not alone. This is what Apple called deferred permission, or provisional permission. Whatever we call it, it means the real “Always Allow” permission will be shown later, at the time decided by iOS system.

Allow Always confirmation comes later (source: WWDC 2019)

In real life, user can expect to see the popup below a few days later:

Actually, this is the real popup for “Always Allow”, which uses your NSLocationAlwaysAndWhenInUseUsageDescription string as message. If user selects “Change to Only While Using”, both app and setting get the permission .authorizedWhenInUse. Otherwise, if user selects “Always Allow”, then both app and setting now get the “true” .authorizedAlways.

This new behaviour in iOS 13 imply frustration for tracking app’s designers. Since app get the “pretended” Always Allow permission at the beginning, user may accidentally “Change to Only While Using” on second confirmation, and disrupt app’s functionality. Many companies had to design a force setting permission screen in their apps to redirect user to location permission in iOS Setting and let users manually choose the correct one.

Improvement for iOS 13.4

Since iOS 13.4, it seems like Apple realized that it need some user experience improvement. So, as I mentioned at the beginning, they decided to allow developer to show the second popup immediately. But it doesn’t come with a straightforward implementation. As stated in requestAlwaysAuthorization documentation in Xcode 11.4:

An application which currently has “when-in-use” authorization and has never before requested “always” authorization may use this method to request “always” authorization one time only

In fact, this means, for a fresh user (never gives any location permission before in app), we must show firstly a “When in Use” request. If user gives “When in Use” permission, then we make the “Always Allow” request to pop the second one. You can inspire from the code below:

Simple, right? In iOS 13.4, we can just setup a closure, so when user answer the first popup, we can detect if they give the “right” choice and if so, show the “Always Allow” request.

Using this code, we will get the desired result:

Happy path’s sequence when running this code on iOS 13.4.

Where to go from here?

If you want to understand deeper in Core Location changes in iOS 13, I suggest the excellent presentation from WWDC 2019: What’s New in Core Location

--

--

Quang NGO
The Startup

iOS Engineer. Passionate in improving mobile development environment. Sharing best practices and how to do better programming