Asking for permission to access location data

When you do need access to a user's location, you have to ask permission first. Similar to how you have to add a reason for needing the camera or a user's contacts to the Info.plist file, you must also provide a reason for requesting location data. In the case of location data, there are two keys you can add to the Info.plist:

  • Privacy-Location When In Use Usage Description (NSLocationWhenInUseUsageDescription)
  • Privacy-Location Always And When In Use Usage Description (NSLocationAlwaysAndWhenInUseUsageDescription)

When your app asks for permission to use a user's location data, they have the option to only allow your app access to their location when the app is in use, or they can choose to allow your app to access their location all the time, even when the app is in the background. You can also configure the type of access that you want to ask yourself. If you only need the user's location when they are using the app, make sure to configure your permission request properly, so the user isn't asked to provide their location to your app when it's in the background.

After adding the required keys to the Info.plist file in the LocationServices app, you will need to write some code to ask the user for permission to use their location. Before doing this, let's quickly examine the sample project's structure and content, so you are aware of what information can be found where.

First, open the Main.storyboard file in the project. You will find a tab bar controller with two view controllers in it. Throughout this chapter, you will implement the features to populate these view controllers with appropriate data. Next, look at the AppDelegate implementation. The implementation here follows the Dependency Injection pattern that you have seen used in earlier projects, so there shouldn't be any surprises for you here. Now, go ahead and examine the view controllers. The GeofenceViewController is the one you will work on first, to make the user's current location appear on the screen.

You will notice that a lot of code has already been implemented in this view controller. Examine the existing code for a bit, and you'll find that all the code makes calls to empty methods in LocationHelper.swift. Most of your focus in this chapter will be on implementing the Core Location code required to work with a user's location data, so the UI work has already been set up. As you add code to LocationHelper, you'll find that the user interface for LocationServices comes to life bit by bit.

Now that you have a better understanding of how the LocationServices app was set up, let's see what steps are involved in asking the user for permission to use their location. Since this app will eventually track location changes in the background, you should ask the user access to their location even when the app is in the background. To do this, add the following viewDidAppear(_:) code to GeofenceViewController:

locationHelper.askPermission { [weak self] status in
  if status == .authorizedAlways {
    self?.showCurrentLocation()
  } else {
    // handle the case where you don't always have access
  }
}

This is the first view controller the user will see, so asking the user for their location as soon is this view appears is a good idea. If it's not obvious that you will be prompting the user for their location, it's often a good idea to inform the user about why you are going to ask them for location permissions before actually showing the location access dialog. To actually make the permission dialog appear, you will need to add some code to LocationHelper.swift.

All location service-related requests are performed through an instance of CLLocationManager. The location manager is responsible for obtaining the user's GPS location, asking for permission to access the user's location, and more. When the location manager receives updates about the user's location, authorization status, or other events, it will notify its delegate. A location manager delegate should conform to the CLLocationManagerDelegate protocol. Note that the LocationHelper already conforms to CLLocationManagerDelegate, and that an instance of CLLocationManager is already created on this object. All that's left to do is assign the helper as the delegate for the location manager. Add the following line at the end of the init() method in LocationHelper to set it as the location manager delegate:

locationManager.delegate = self

Next, add the following implementation for the askPermission(_:) method:

func askPermission(_ completion: @escaping (CLAuthorizationStatus) -> Void) {
  let authorizationStatus = CLLocationManager.authorizationStatus()
  if authorizationStatus != .notDetermined {
    completion(authorizationStatus)
  } else {
    askPermissionCallback = completion
    locationManager.requestAlwaysAuthorization()
  }
}

This implementation checks whether a current authorization status exists. If it does, the completion callback is called with the current status. If the current status has not been determined yet, the location manager is asked to request authorization to access the user location using the requestAlwaysAuthorization() method. This will prompt the user for their location permissions. The reason you need to have permanent access to a user's location in this app is to ensure you can implement geofencing later in this chapter. Add the following method to the CLLocationManagerDelegate to retrieve the user's response to the authorization prompt:

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
  askPermissionCallback?(status)
  askPermissionCallback = nil
}

The preceding code immediately passes the user's response to the stored completion callback that was passed to askPermission(_:). After calling the callback, it is set to nil to avoid accidentally calling it again. At this point, you have done all the work required to request access to a user's location. Let's see how you can retrieve a user's current location next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.247.196