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.

comments powered by Disqus