What’s New With Privacy?

Learn about the new privacy features introduced in iOS 14.5, including accessing the new privacy-focused image picker, handling location permissions and more. By Renan Benatti Dias.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Working with Location Services

Just like photos, the user’s location is a quite personal piece of data that not all users want to share with every app. Starting with iOS 14, apps have to ask permission to access the user’s location and also how often they can access this data. Instead of just allowing or denying access to their location, users can now choose to Always Allow or Allow While Using App. They can also choose to Allow Once. That way, iOS asks permission the next time the user opens the app.

Users can also decide the extent of the accuracy of their location data. Instead of giving a precise location, iOS gives an approximate location of the user, already enough for features that look for locations around them.

This helps give the user control over when and how the app accesses their location. The user has full control over this, with the ability to change each app authorization and accuracy whenever they want, using the Settings app.

Designing for Location Privacy

Some apps, such as Apple Maps, require full accuracy for some features to work properly. Precise location affects the estimated time of arrival, relevant places and even navigation.

These apps have to adapt their UI and features to give an optimal experience, either for when the user prefers using precise location or not.

While using precise location, Apple Maps uses a pulsating blue dot on the map to show the user’s location.

Apple Maps with a pulsating blue dot indicating the user's location

With precise location off, this dot turns into a shaded circular area, displaying a general location of the user. Also, notice the text at the top of the view indicating precise location is off.

Apple Maps with a shaded circular blue area indicating a general location of the user and a button at the top of the view explaining precise location is off

These UI changes indicate the state of accuracy on Apple Maps.

Other changes were made to features that require precise location. While precise location is off, Apple Maps Favorites don’t show an estimated time of arrival (ETA). Calculating an ETA requires precise data. An approximate location could compromise an ETA.

Favorites places displayed without ETA

While designing your app, you must keep in mind users might not want to share their precise location. Giving the user power to choose makes them feel safer and in control of their data.

Adding Location Data

Now that you know how important it is to be transparent with the user’s location data, it’s time to add location to the picture. To do this, you’ll add a button for asking authorization to access the user’s location and to show a map displaying their location.

Open NewPictureStore.swift and add the following under hasLocation:

private lazy var locationManager: CLLocationManager = {
  let manager = CLLocationManager()
  manager.delegate = self
  return manager
}()

This code adds a lazy property of CLLocationManager you’ll use to track the user’s location. Xcode triggers a compiler error because NewPictureStore does not conform to CLLocationManagerDelegate. You’ll fix that later, but first add the following properties after hasLocation:

@Published 
var locationAuthorizationStatus: CLAuthorizationStatus = .notDetermined
@Published 
var locationAccuracyAuthorization: CLAccuracyAuthorization = .reducedAccuracy

The first property tracks the app’s authorization status to use location services. The second property tracks the accuracy preferred for this app by the user.

The app’s authorization status can be either:

  1. .notDetermined: The user has not yet chosen to allow or prevent location data to this app.
  2. .restricted: The app is not authorized to use location services, not necessarily because the user denied access.
  3. .denied: The user denied access to location services or location services is disabled in Settings.
  4. .authorizedAlways: The app has the authorization to use location services whenever the app requires it, even in the background.
  5. .authorizedWhenInUse: The user has authorized use of location services only while the app is in the foreground.

The accuracy of location data can be either .fullAccess, when the app has authorization to the full accuracy data, or .reducedAccuracy, meaning the app has only the user’s approximate location.

Next, add the following method at the end of the class:

func updateLocationAndAccuracyStatus() {
  // 1
  locationAuthorizationStatus = locationManager.authorizationStatus
  // 2
  locationAccuracyAuthorization = locationManager.accuracyAuthorization
}

This method does two things:

  1. Updates the current location authorization status.
  2. Updates the current accuracy authorization.

You’ll use this method to update both properties whenever location or accuracy status changes.

Conforming to CLLocationManagerDelegate

To conform NewPictureStore to CLLocationManagerDelegate, add the following extension at the end of the file:

// MARK: - CLLocationManagerDelegate
extension NewPictureStore: CLLocationManagerDelegate {
  // 1
  func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
    updateLocationAndAccuracyStatus()
  }

  // 2
  func locationManager(
    _ manager: CLLocationManager, 
    didUpdateLocations locations: [CLLocation]
  ) {
    guard let userLocation = locations.first else { return }
    self.userLocation.center = userLocation.coordinate
  }
}

Here’s a breakdown of what’s happening in each method:

  1. CLLocationManager calls locationManagerDidChangeAuthorization(_:) whenever a change happens on the app’s location authorization. When that happens, you update both properties with updateLocationAndAccuracyStatus().
  2. CLLocationManager calls this method whenever new location data is available. Then, you update the user location property with the latest data.

This handles updating location data, location accuracy and location authorization. Now, you’ll add code to show the user’s location on a map and request authorization for said feature.

Showing User Location on Map

Add the following extension at the bottom of NewPictureStore.swift:

// MARK: - Location Authorization
extension NewPictureStore {
  // 1
  var locationIsDisabled: Bool {
    locationAuthorizationStatus == .denied ||
      locationAuthorizationStatus == .notDetermined ||
      locationAuthorizationStatus == .restricted
  }

  // 2
  var showAllowLocationButton: Bool {
    locationAuthorizationStatus == .notDetermined
  }

  // 3
  func requestLocationAuthorization() {
    locationManager.requestWhenInUseAuthorization()
  }

  // 4
  func startUpdatingUserLocation() {
    locationManager.startUpdatingLocation()
  }
}

The code above creates an extension with a couple of handy properties and methods. Here’s what they do:

  1. locationIsDisabled is a Boolean to disable the location section if the user has denied access to location data.
  2. showAllowLocationButton is a Boolean to show a button if iOS didn’t ask for location services permission yet.
  3. This method calls requestWhenInUseAuthorization() to show an alert requesting authorization to access location data.
  4. And finally, this method calls startUpdatingLocation() to start updating the user’s location data.

Now, open NewPictureView.swift, find the following line inside locationSection:

.disabled(true)

And replace it with this:

.disabled(store.locationIsDisabled)

This makes sure the location section will be disabled only if the user didn’t authorize access to location data.

Next, find // TODO: Add map here and add the following code below the comment:

if store.hasLocation {
  MapWithLocation(coordinates: $store.userLocation)
    .onAppear(perform: store.startUpdatingUserLocation)
  // TODO: Precise location off button
}

MapWithLocation is a custom SwiftUI view that has a Map and a Text with latitude and longitude. When it appears on the view, the modifier onAppear(perform:) calls startUpdatingUserLocation() to update the user’s location.

Finally, find // TODO: Add allow location data button here and add this code under:

if store.showAllowLocationButton {
  Button("Allow Location Data", action: store.requestLocationAuthorization)
}

This adds the button to ask for authorization for the app to access location data.

Build and run and tap the new button to allow location.

A form with a button to open an image picker view, field for caption and a location section with an allow button

Nothing happened! But check out the console in Xcode.

Xcode terminal displaying an error to add a description for using location when in use of the app.

To ask authorization to access location data, you need to add a string to Info.plist that iOS uses to explain to users why your app requires access to their location. That’s why nothing happens when you tap the button.