I am the author of iOS 17 Fundamentals, Building iOS User Interfaces with SwiftUI, and eight other courses on Pluralsight.
Deepen your understanding by watching!
Swift Cheat Sheet for iPhone Location Services Access and Usage
This is a cheat sheet of the code and workflow for iPhone location access and usage, from requesting permission to using the location of the user’s device.
Framework Import
import CoreLocation
Set Location Usage Description in Info.plist
This is a required first step
If you don’t set this, your app simply won’t present the user with the system alert to request access to the location (and, of course, you won’t be getting any location data for your app either).
When you request permission to use the device’s location, a short message will appear in the default iOS system dialog. You customize this message by adding one of the following keys to your Info.plist file:
- Privacy – Location Always and When In Use Usage Description
- Privacy – Location Always Usage Description
- Privacy – Location When In Use Usage Description
For the value of this plist property, type a short string describing what you’re using the location for.
Initialize CLLocationManager and Implement CLLocationManagerDelegate
CLLocationManager
is the name of the class that gives you a way to request location services permission. It is also responsible for starting the location tracking process.
It needs a corresponding CLLocationManagerDelegate
to be assigned. The location manager instance you initialize will alert you to location services authorization changes (ie, if the user turns off location services permissions for your app) through the one of the methods that your delegate class implements.
The location manager instance will also send you the user’s current location through one of the methods your delegate class implements.
Here is an example of initializing the CLLocationManager
instance, and setting its delegate.
There’s also a currentLocation
variable that will get continually updated…
1class NameOfViewController: UIViewController, CLLocationManagerDelegate {
2 private let locationManager = CLLocationManager()
3
4 // This will get updated via the location manager delegate's didUpdateLocations method
5 var currentLocation: CLLocation? = nil
6
7 override func viewDidLoad() {
8 super.viewDidLoad()
9
10 // Do any additional setup after loading the view.
11
12 locationManager.delegate = self
13
14 self.startLocationServices() // This function is implemented below...
15 }
16}
Here is an example of how to implement the two CLLocationManagerDelegate
methods:
1// Monitor location services authorization changes
2func locationManager(_ manager: CLLocationManager,
3 didChangeAuthorization status: CLAuthorizationStatus) {
4 switch status {
5 case .notDetermined:
6 break
7 case .authorizedWhenInUse, .authorizedAlways:
8 if CLLocationManager.locationServicesEnabled() {
9 self.locationManager.startUpdatingLocation()
10 }
11 case .restricted, .denied:
12 self.alertLocationAccessNeeded()
13 }
14
15// Get the device's current location and assign the latest CLLocation value to your tracking variable
16func locationManager(_ manager: CLLocationManager,
17 didUpdateLocations locations: [CLLocation]) {
18 self.currentLocation = locations.last
19 }
20}
Start Location Services, Check Location Authorization Status, Request Permission
When you first start location services in your app, you will want to immediately check your app’s current authorization status for location services, just in case the user has gone in and disabled location services permission for your app since the last time he/she used it.
If it’s the first time the user has launched your app, the .notDetermined
case will get hit. This is where you request permission for the first time.
If the user grants permission, you can use the CLLocationManager
instance that your class is using to start updating the user’s location.
If, however, the user denies permission, you can alert them to the fact that your app needs access to his/her location for [insert some good reason here].
Here’s a code snippet showing this in action:
1func startLocationServices() {
2 locationManager.desiredAccuracy = kCLLocationAccuracyBest
3
4 let locationAuthorizationStatus = CLLocationManager.authorizationStatus()
5
6 switch locationAuthorizationStatus {
7 case .notDetermined:
8 self.locationManager.requestWhenInUseAuthorization() // This is where you request permission to use location services
9 case .authorizedWhenInUse, .authorizedAlways:
10 if CLLocationManager.locationServicesEnabled() {
11 self.locationManager.startUpdatingLocation()
12 }
13 case .restricted, .denied:
14 self.alertLocationAccessNeeded()
15 }
16}
Note: You can test for the .notDetermined
case by deleting the app on the device, if it’s already been installed or run on a device from the debugger.
Alert Location Services Access Needed
If location services access has been denied or restricted, you can alert the user and direct them to the Settings app to make the appropriate permissions adjustment:
1func alertLocationAccessNeeded() {
2 let settingsAppURL = URL(string: UIApplicationOpenSettingsURLString)!
3
4 let alert = UIAlertController(
5 title: "Need Location Access",
6 message: "Location access is required for including the location of the hazard.",
7 preferredStyle: UIAlertControllerStyle.alert
8 )
9
10 alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
11 alert.addAction(UIAlertAction(title: "Allow Location Access",
12 style: .cancel,
13 handler: { (alert) -> Void in
14 UIApplication.shared.open(settingsAppURL,
15 options: [:],
16 completionHandler: nil)
17 }))
18
19 present(alert, animated: true, completion: nil)
20}
Note: You can test for this case (.restricted
and .denied
) by going to the Settings app and turning off location services access for your app, if it’s been previously granted.