How To Get Current Location in Swift

By Eddy Chung

Getting a users current location is important for many applications.

It helps provide a better user experience by localizing the app. Users can find more relevant items near them. Let’s take a look how we can solve this problem in Swift.

Get current location in Swift

To get a user’s current location, you’ll first need to import MapKit and CoreLocation in the top of your view controller.

import MapKit
import CoreLocation

Next you’ll need to create a CLLocationManager

let locationManager = CLLocationManager()

You will have to decide whether your application will need the users location always (even when in it’s in the background) or only when the apps in use.

To request location authorization always, use this line of code:

locationManager.requestAlwaysAuthorization()

Otherwise, to request location authorization when the app is in use:

locationManager.requestWhenInUseAuthorization()

Now make sure your ViewController subclasses CLLocationManagerDelegate:

class ViewController: UIViewController, CLLocationManagerDelegate {
    ...
}

We can now set our location manager to update:

if CLLocationManager.locationServicesEnabled() {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
    locationManager.startUpdatingLocation()
}

The location manager will update the delegate function. We’ll add some code in our delgate function to print out the location:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
    print("locations = \(locValue.latitude) \(locValue.longitude)")
}

Now run your application. You’ll notice in console, you’ll get some errors:

This app has attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain both “NSLocationAlwaysAndWhenInUseUsageDescription” and “NSLocationWhenInUseUsageDescription” keys with string values explaining to the user how the app uses this data

Not to worry, this is expected. This means we have to update our Info.plist file. Open it up from the Project Navigator:

make_56

Right click and select Add Row. Paste in NSLocationWhenInUseUsageDescription into the Information Property List column of your newly added row. Set it’s type to string and then set its value to a message you’d like to display to the user.

For example, I can put “We’ll use this to personalize your app experience”. The permissions dialog will look like so:

make_57

If you’ve requested for location access always, you’ll need to do add another row for NSLocationAlwaysAndWhenInUseUsageDescription

Your Info.plist rows should look something like this:

make_58

That’s it, you should be able to run your application and see the users location data printed into console (using our example code). The users location will be printed every time it changes.

Here’s the full example code for this article (only 23 lines of code!):

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {
    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.requestAlwaysAuthorization()
        locationManager.requestWhenInUseAuthorization()
        if CLLocationManager.locationServicesEnabled() {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
            locationManager.startUpdatingLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
        print("locations = \(locValue.latitude) \(locValue.longitude)")
    }
}

Your console should output something like this:

locations = 37.785834 -122.406417

If you’re using the simulator, you’ll notice that the user location isn’t being updated. That’s because you need to simulate location in the iOS simulator.

How To Simulate Location On iOS Simulator

Changing locations on the simulator is a great way to test features of your application, without physically having to move to different locations.

To change the location on your iOS simulator go to Debug > Location > Custom Location

make_59

Here you will be able to set the longitude and latitude to any location.

make_60

To get the longitude and latitude of a location in Google Maps, right click and select “What’s here”.

make_61

Then at the bottom of your screen, the longitude and latitude will be displayed.

make_62

How To Get City And Country From Longitude And Latitude

To get the city and country from a longitude and latitude, we must do a reverse geo-code. In swift, it’s quite simple to do:

Here’s a function that you can copy and paste into your code:

func fetchCityAndCountry(from location: CLLocation, completion: @escaping (_ city: String?, _ country:  String?, _ error: Error?) -> ()) {
    CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
        completion(placemarks?.first?.locality,
                   placemarks?.first?.country,
                   error)
    }
}

We use it in our example code like so:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let location: CLLocation = manager.location else { return }
    fetchCityAndCountry(from: location) { city, country, error in
        guard let city = city, let country = country, error == nil else { return }
        print(city + ", " + country)
    }
}

Our console output is:

San Francisco, United States

Get Current Locale

The locale is a setting the user sets their iOS device to. It controls the language and other formatting options.

It can tell you what country the user is from, or at least what country their device is currently set to.

To get the current device locate, you can use the following code:

let locale = Locale.current
print(locale)

Since my device is set to English (US), this printed out:

en_US

You can view a list of locales here.

If you liked this post, you'll love my free guide: Secrets To iOS Development. Speed up your learning curve - hundreds of students have already downloaded. Thanks for reading!
Profile Picture of Eddy Chung

Eddy Chung

I am a professional iOS developer in Silicon Valley. I teach iOS development on ZeroToAppStore.com. If you'd like to learn more about me click here or you can contact me at: eddy@zerotoappstore.com

Similar Posts