How to Access the User's Location in iOS Apps (2022)

Hello World! In this post, we’re going to look at howwe can retrievethe user’s location as pure data and as a position ona map. We’ll look into the CoreLocation andMapKitmodules and build an app that will display some diagnostic information like latitude, longitude, altitude, and accuracy. Right underneath those fields, we’ll have amap view thatwill animate to the user’s location automatically. We’ll alsolearn how to simulate location using theiOS simulator.

BUILD GAMES
How to Access the User's Location in iOS Apps (1)

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Download the source code for this project here.

Learn iOS by building real apps

Check out The Complete iOS Development Course – Build 14 Apps with Swift 2 on Zenva Academy to learn Swift 2 and iOS development from the ground-up with an expert trainer.

Let’s create a new Single-ViewiOS app in Xcode called FindMe. We’re going to build our UI first. We’ll need several static UILabels andequally as many dynamic ones to displayvarious diagnostic information like latitude,longitude, altitude, and accuracy.Refer to thescreenshot below on how to position these views.

Regarding autolayout, we can use a shortcut to automatically remove any ambiguity in our view. Selectthe view controller andopenup theResolve Conflicts menu on the bottom right (to the right of the pin menu).Select Reset to Suggested Constraints.

This willautomatically add autolayout constraintsbased on how we positioned the viewsin the view controller. Eventhough this is automatic, we should still check the resultsto make sure there isn’t a constraintthat wedon’t want applied. In our case, there doesn’t seem to be any so let’s move on to some source code.

Let’s create outlets to all of the labels on the right side. Control-drag and name them latitudeLabel, longitudeLabel, altitudeLabel, hAccuracyLabel, andvAccuracyLabel, respectively. We don’t need to createoutlets for the UILabelson the left side since those labels have static text so we don’t have to reference them for anything.

In addition, we’ll need to import CoreLocation right under the import to UIKit. In addition to the labels, let’s create another variablecalled locationManager of type CLLocationManager and initialize it. Thisclass is what we’ll use torequestthe user’s location. Our entire Swift file should looklike the following.

import UIKitimport CoreLocationclass ViewController: UIViewController { @IBOutlet weak var latitudeLabel: UILabel! @IBOutlet weak var longitudeLabel: UILabel! @IBOutlet weak var altitudeLabel: UILabel! @IBOutlet weak var hAccuracyLabel: UILabel! @IBOutlet weak var vAccuracyLabel: UILabel! var locationManager: CLLocationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. }}

Nowwe have to configure the location manager and request the user for permission toretrieve location. Wecan do this in theviewDidLoad method. First, we need to set the level of accuracywe want. There aremany different levels ofaccuracy we can request. Keep in mind that the higher level ofaccuracy we request, the more battery life we’re going to consume.We should set the desiredAccuracy to be theleast accuratethat willstill allow our app to function smoothly.

For example, if we were building anavigation app, we want high accuracy since the user is probably driving. However, if we were building a weather app, we don’t need very accurate location on the user; perhaps a general vicinity will work fine. Since we’re runningour app on the simulator and simulation alocation, we can simply select the best accuracy available.

We need to set the delegate to be self. When we do this, we also need to conform to the CLLocationManagerDelegate in our class declaration.Next, we need to eitherrequestauthorization to retrieve location only when the app is in use or always. Forprivacy reasons,we shouldonly request authorization when our app is in use. Finally, we can call startUpdatingLocation toreceive location updates.

Our entire viewDidLoadmethod should looklike the code snippet below.

override func viewDidLoad() { super.viewDidLoad() locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation()}

When we requestpermission for the user’s location, we can give them a custom message to explain why we want to access their location.We should always do this! Butwe don’t set this string in the source code; we set this constant inthe Info.plist file in the project.

On the left pane, find the Info.plist file and open it up. This is a Property List file that contains configuration information essential to the app. In our case, we need to right-click on the top level entry and select AddRow.In the new row,setitskey to be NSLocationWhenInUseUsageDescription. For the value, set it to be something descriptive. This description needs to provide a reason to the user. If your app needs the user’s location for a valid purpose, explain that purpose. We don’t want our location permission to be rejected on the grounds that the user thought our description wasn’t descriptive!

Furthermore, this key in the Info.plist file is required to get authorization for our app. If we didn’t have this in the Info.plist file, then the user would never receive that authorization dialog, and location permissions would be rejected by default.Take a look at the screenshot for reference.

Now that we’re finished withthis configuration, let’s get back to the Swift file and implement thedelegate methods of the CLLocationManagerDelegate. The one we’reparticularly interested in is the locationManager:didUpdateLocations method.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { }

We canretrieve the last location ofthe user and set those diagnostics in this method. We first need to grab themost recent location of the user by retrieving the last element in the array. Then wecan use theproperties onthatCLLocation object to set the diagnostic labels. We’re using a String format to convert the properties to a human-readable format.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let lastLocation: CLLocation = locations[locations.count - 1] latitudeLabel.text = String(format: "%.6f", lastLocation.coordinate.latitude) longitudeLabel.text = String(format: "%.6f", lastLocation.coordinate.longitude) altitudeLabel.text = String(format: "%.6f", lastLocation.altitude) hAccuracyLabel.text = String(format: "%.6f", lastLocation.horizontalAccuracy) vAccuracyLabel.text = String(format: "%.6f", lastLocation.verticalAccuracy)}

Now let’s try running our app!

The first thing we see is the authorization dialog! Then we see the location appear! Success! This particular location is Apple’s headquarters in the U.S. We canchangethe simulated location on thesimulator by going to Debug->Location in the menu bar.

For this next part ofthe post, we’re going to see how to use a MapKit MapViewin conjunction with ourCoreLocationconfiguration we already set up in the previous part of the post. Let’s go back to our storyboard and add theMapKit MapView to fill the bottomof the view controller.

For autolayout, select it and go to the Resolve Conflicts menu. Select Reset to Suggested Constraints in the Selected View subsection. That should automatically add autolayout constraints.Next, we need to create an outlet to it in our Swift class called mapView. We’ll get an error about not being able to find MKMapView. We need to import the MapKit module right under the import statement for CoreLocation.

We want to center and animate the map to the user’s current location. However, the latitude and longitude are not enough toaccomplish this task. We also need to specify a region to animate to. For convenience, let’s create a function to do this calledanimateMap.In thismethod, we’ll create a region andanimate the mapView to that region.

func animateMap(_ location: CLLocation) { let region = MKCoordinateRegionMakeWithDistance(location.coordinate, 1000, 1000) mapView.setRegion(region, animated: true)}

In the above code snippet, we’re creating a region whose center is the coordinate ofthe CLLocation object passed in. The region is a rectangular region with a width and heigh of 1000 meters. Finally, we set the mapView’s region and tell it to animate itselfto that region.

We alsowant that blue dotto show the user’s current location. To do this, we have to configure a property onthe mapView object. Set it’s showsUserLocation property to be true inthe viewDidLoad method.

override func viewDidLoad() { super.viewDidLoad() locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() mapView.showsUserLocation = true}

Now when we get the last location of the user, we can also animate the map to that location using the animateMap function.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let lastLocation: CLLocation = locations[locations.count - 1] latitudeLabel.text = String(format: "%.6f", lastLocation.coordinate.latitude) longitudeLabel.text = String(format: "%.6f", lastLocation.coordinate.longitude) altitudeLabel.text = String(format: "%.6f", lastLocation.altitude) hAccuracyLabel.text = String(format: "%.6f", lastLocation.horizontalAccuracy) vAccuracyLabel.text = String(format: "%.6f", lastLocation.verticalAccuracy) animateMap(lastLocation)}

To recap, below isthe full source code for the entire class.

import UIKitimport CoreLocationimport MapKitclass ViewController: UIViewController, CLLocationManagerDelegate { @IBOutlet weak var latitudeLabel: UILabel! @IBOutlet weak var longitudeLabel: UILabel! @IBOutlet weak var altitudeLabel: UILabel! @IBOutlet weak var hAccuracyLabel: UILabel! @IBOutlet weak var vAccuracyLabel: UILabel! @IBOutlet weak var mapView: MKMapView! var locationManager: CLLocationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() mapView.showsUserLocation = true } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let lastLocation: CLLocation = locations[locations.count - 1] latitudeLabel.text = String(format: "%.6f", lastLocation.coordinate.latitude) longitudeLabel.text = String(format: "%.6f", lastLocation.coordinate.longitude) altitudeLabel.text = String(format: "%.6f", lastLocation.altitude) hAccuracyLabel.text = String(format: "%.6f", lastLocation.horizontalAccuracy) vAccuracyLabel.text = String(format: "%.6f", lastLocation.verticalAccuracy) animateMap(lastLocation) } func animateMap(_ location: CLLocation) { let region = MKCoordinateRegionMakeWithDistance(location.coordinate, 1000, 1000) mapView.setRegion(region, animated: true) }}

Now let’srun our app and see our map!

It works! We can see the diagnosticUILabels show data, and theMKMapView shows the location and the blue dot for the user’s currentlocation.

In this post,we saw how to usethe CoreLocation module to request the user’s current location. We learned the different levels of accuracy and the different types of authorization.We then looked at theMapKitmoduleand saw how to use the MKMapView to display the user’slocation and animate to the region of the user automatically.

Related Posts

Top Articles

You might also like

Latest Posts

Article information

Author: Geoffrey Lueilwitz

Last Updated: 10/10/2022

Views: 6601

Rating: 5 / 5 (60 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Geoffrey Lueilwitz

Birthday: 1997-03-23

Address: 74183 Thomas Course, Port Micheal, OK 55446-1529

Phone: +13408645881558

Job: Global Representative

Hobby: Sailing, Vehicle restoration, Rowing, Ghost hunting, Scrapbooking, Rugby, Board sports

Introduction: My name is Geoffrey Lueilwitz, I am a zealous, encouraging, sparkling, enchanting, graceful, faithful, nice person who loves writing and wants to share my knowledge and understanding with you.