Find city name and country from latitude and longitude in Swift

get latitude and longitude from address swift 4
get city name from latitude and longitude swift 3
how to get location using latitude and longitude in swift
get address from latitude and longitude ios swift
reversegeocodelocation swift 4
get address from latitude and longitude google map swift
gmsgeocoder swift
place name from latitude and longitude

I'm working on application in Swift3 and I have letter problem i can't find the answer for it.

How can I know city name and country short names base on latitude and longitude?

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate{
    let locationManager = CLLocationManager()
    var latitude: Double = 0
    var longitude: Double = 0
    override func viewDidLoad() {
        super.viewDidLoad()
        // For use when the app is open & in the background
        locationManager.requestAlwaysAuthorization()
        // For use when the app is open
        //locationManager.requestWhenInUseAuthorization()
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
        if CLLocationManager.locationServicesEnabled() {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.startUpdatingLocation()
        }
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let location = locations.first {
            print(location.coordinate)
            latitude = location.coordinate.latitude
            longitude = location.coordinate.longitude
        }
    }
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if (status == CLAuthorizationStatus.denied){
            showLocationDisabledpopUp()
        }
    }
    func showLocationDisabledpopUp() {
        let alertController = UIAlertController(title: "Background Location Access  Disabled", message: "We need your location", preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
        alertController.addAction(cancelAction)
        let openAction = UIAlertAction(title: "Open Setting", style: .default) { (action) in
            if let url = URL(string: UIApplicationOpenSettingsURLString){
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
        }
        alertController.addAction(openAction)
        self.present(alertController, animated: true, completion: nil)
    }
}

I would recommend integrating Google Maps API with your project. If you do, your task can be achieved using Reverse Geocoding Google provides.

Furthermore, Google there is Google Maps SDK for IOS development, which is also worth considering.

UPD: You can do that without integrating maps into your project. Basing on this answer, you can achieve that using http requests to Google API. The request to:

https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=API_KEY 

would return JSON object with information about the requested place, including country and city name.

BTW, I highly recommend using Alamofire to make http requests in Swift.

Convert coordinates to City name?, Then I have set up a class to get the desired data like zip, town, country: location = CLLocation(latitude: 37.3321, longitude: -122.0318) CLGeocoder(). Thanks to @Kampai's answer, here's a Swift 3 compatible and safer way (no forcing ! ): Latitude and Longitude Finder. Latitude and Longitude are the units that represent the coordinates at geographic coordinate system.To make a search, use the name of a place, city, state, or address, or click the location on the map to find lat long coordinates.

You can use CLGeocoder reverseGeocodeLocation method to fetch a CLPlacemark and get its country and locality properties info. Note that it is an asynchronous method so you will need to add a completion handler to your method when fetching that info:

import UIKit
import MapKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

extension CLLocation {
    func fetchCityAndCountry(completion: @escaping (_ city: String?, _ country:  String?, _ error: Error?) -> ()) {
        CLGeocoder().reverseGeocodeLocation(self) { completion($0?.first?.locality, $0?.first?.country, $1) }
    }
}

Usage

let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
location.fetchCityAndCountry { city, country, error in
    guard let city = city, let country = country, error == nil else { return }
    print(city + ", " + country)  // Rio de Janeiro, Brazil
}

Converting Between Coordinates and User-Friendly Place Names , Convert between a latitude/longitude pair and a more user-friendly which contains properties for specifying the street name, city name, country name, postal  Find Country list with popular places, their states and latitude and longitude. select any country to list cities or places categories with latitude and longitude. Toggle navigation Distance Calculator

What you need is called reverse geocoding. As you have already declared some properties at the top. You need to add the CLGeocoder & CLPlancemark

let locationManager = CLLocationManager()
var location: CLLocation?

let geocoder = CLGeocoder()
var placemark: CLPlacemark?

// here I am declaring the iVars for city and country to access them later

var city: String?
var country: String?
var countryShortName: String?

Create a function where you can start the location services

func startLocationManager() {
    // always good habit to check if locationServicesEnabled
    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.startUpdatingLocation()
    }
}

also create another to stop once you're done with location geocoding

func stopLocationManager() {
   locationManager.stopUpdatingLocation()
   locationManager.delegate = nil
}

in view didLoad or from anywhere you want to start the location manager add a check first

override func viewDidLoad() {
super.viewDidLoad()

    let authStatus = CLLocationManager.authorizationStatus()
    if authStatus == .notDetermined {
        locationManager.requestWhenInUseAuthorization()
    }

    if authStatus == .denied || authStatus == .restricted {
        // add any alert or inform the user to to enable location services 
    }

   // here you can call the start location function
   startLocationManager()

}

implement the delegate methods for location manager didFailedWithError

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    // print the error to see what went wrong
    print("didFailwithError\(error)")
    // stop location manager if failed
    stopLocationManager()
}

implement the delegate method for location manager didUpdateLocations

 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    // if you need to get latest data you can get locations.last to check it if the device has been moved
    let latestLocation = locations.last!

    // here check if no need to continue just return still in the same place
    if latestLocation.horizontalAccuracy < 0 {
        return
    }
    // if it location is nil or it has been moved
    if location == nil || location!.horizontalAccuracy > lastLocation.horizontalAccuracy {

        location = lastLocation
        // stop location manager
        stopLocationManager()

        // Here is the place you want to start reverseGeocoding
        geocoder.reverseGeocodeLocation(lastLocation, completionHandler: { (placemarks, error) in
                // always good to check if no error
                // also we have to unwrap the placemark because it's optional
                // I have done all in a single if but you check them separately 
                if error == nil, let placemark = placemarks, !placemark.isEmpty {
                    self.placemark = placemark.last
                }
                // a new function where you start to parse placemarks to get the information you need
                self.parsePlacemarks()

           })
    }
}

Add the parsePlacemarks function

parsePlacemarks() {
   // here we check if location manager is not nil using a _ wild card 
   if let _ = location {
        // unwrap the placemark 
        if let placemark = placemark {
            // wow now you can get the city name. remember that apple refers to city name as locality not city
            // again we have to unwrap the locality remember optionalllls also some times there is no text so we check that it should not be empty
            if let city = placemark.locality, !city.isEmpty {
                // here you have the city name
                // assign city name to our iVar
                self.city = city
            }
            // the same story optionalllls also they are not empty
            if let country = placemark.country, !country.isEmpty {

                self.country = country
            }
            // get the country short name which is called isoCountryCode
            if let countryShortName = placemark.isoCountryCode, !countryShortName.isEmpty {

                self.countryShortName = countryShortName
            }

        }


    } else {
       // add some more check's if for some reason location manager is nil
    }

}

You have to cmd+click on CLPlacemark to see all the properties that you can access for example street name is called thoroughfare & the number is is called subThoroughfare continue reading the documentation for more information

Note: You have to check for locations error also geocoder error which I haven't implemented here but you have to take care of those errors and the best place to check error codes and everything else is apples documentation

Update: Check paresPlacemarks function where I added isoCountryCode which is equal to country shortName No need to add extra network calls to google API and Alamofire while your already using location services

Swift 101. Convert coordinates to city names and back, In this article I will explain how to get the names of the city, country, zip code, etc from a geo location object and the other way around. The first thing we need to  get timezone and location name using latitude and longitude in C# Get geocode from latitude and longitude Get country, state, zip code and Latitude and Longitude from an ip address

Here is the Swift 4 code:

  var locationManager = CLLocationManager()

  override func viewDidLoad() {
    super.viewDidLoad()
    locationManager.delegate = self
    locationManager.requestWhenInUseAuthorization()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.startUpdatingLocation()
    locationManager.startMonitoringSignificantLocationChanges()
    // Here you can check whether you have allowed the permission or not.
    if CLLocationManager.locationServicesEnabled()
    {
        switch(CLLocationManager.authorizationStatus())
        {
        case .authorizedAlways, .authorizedWhenInUse:
            print("Authorize.")
            let latitude: CLLocationDegrees = (locationManager.location?.coordinate.latitude)!
            let longitude: CLLocationDegrees = (locationManager.location?.coordinate.longitude)!
            let location = CLLocation(latitude: latitude, longitude: longitude) //changed!!!
            CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
                if error != nil {
                    return
                }else if let country = placemarks?.first?.country,
                    let city = placemarks?.first?.locality {
                    print(country)
                    self.cityNameStr = city
                }
                else {
                }
            })
            break

        case .notDetermined:
            print("Not determined.")
            self.showAlertMessage(messageTitle: "Bolo Board", withMessage: "Location service is disabled!!")
            break

        case .restricted:
            print("Restricted.")
            self.showAlertMessage(messageTitle: "Bolo Board", withMessage: "Location service is disabled!!")
            break

        case .denied:
            print("Denied.")
        }
    }
}

func showAlertMessage(messageTitle: NSString, withMessage: NSString) ->Void  {
    let alertController = UIAlertController(title: messageTitle as String, message: withMessage as String, preferredStyle: .alert)
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action:UIAlertAction!) in

    }
    alertController.addAction(cancelAction)

    let OKAction = UIAlertAction(title: "Settings", style: .default) { (action:UIAlertAction!) in
        if let url = URL(string: "App-Prefs:root=Privacy&path=LOCATION/com.company.AppName") {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                // Fallback on earlier versions
            }
        }
    }
    alertController.addAction(OKAction)
    self.present(alertController, animated: true, completion:nil)
}

Tutorial: Geocoding with Swift 4. - Enrico Piovesan, A guide to convert an address to a location point (latitude, longitude) using the the street, city, state, and country information corresponding to the given location, Firstly we try to use the method geocode() to get a Geocoding Object thought  The CLLocation Manager object reports locations as a latitude/longitude pair. While these values uniquely represent any location on the planet, they are not values that users immediately associate with the location. Users are more familiar with names that describe a location, such as street names or city names.

You can use CLGeocoder, from CoreLocation, for that. From Apple documentation (emphasizes mine):

A single-shot object for converting between geographic coordinates and place names.

The CLGeocoder class provides services for converting between a coordinate (specified as a latitude and longitude) and the user-friendly representation of that coordinate. A user-friendly representation of the coordinate typically consists of the street, city, state, and country information corresponding to the given location...

This service is unrelated to MapKit and, as such, don't require you use/show a map in your app at all.

Reverse Geocoding With CLGeocoder, Open ReverseGeocodingViewController.swift and create five outlets as shown below. The text fields are used for entering the latitude and longitude. to Reverse Geocode Location (\(error))") locationLabel.text = "Unable to Find Address for Location" } else It stores data, such as country, city, and street. CLGeocoder class is used to get the location from address and address from the location (coordinates). The method reverseGeocodeLocation will returns the address details from coordinates. This method accepts CLLocation as a parameter and returns CLPlacemark, which contains address dictionary.

MapboxGeocoder.swift/MBGeocodeOptions.swift at master · mapbox , Address search and reverse geocoding in Swift or Objective-C on iOS, macOS _Forward geocoding_ takes a human-readable query, such as a place name or To find out what kinds of results are available for a particular country, consult queries = coordinates.map { String(format: "%.5f,%.5f", $0.longitude, $0.latitude) }​. Enter any address, city, country, province, state or zip code to find its latitude and longitude. Examples: Paris, Texas - Springfield, Illinois - Georgetown, Guyana - Eiffel Tower. You can also enter latitude and longitude coordinates to see their location on a map. To do so, please use this format.

Developer Guide | Geocoding API, You can also use the Geocoding API to find the address for a given place ID. Examples of address types include a street address, a country, or a political entity​. alternative name for the entity. locality indicates an incorporated city or town political The bounds parameter defines the latitude/longitude coordinates of the  GPS Coordinates Finder. Latitude and Longitude Finder to find GPS coordinates, my location or where am I right now including my address, current latitude and longitude. Get my coordinates from address, or find address from Lat Long. Search for any address and find latitude and longitude on the map coordinates.

Search service | API, country, Generally recognized countries or, in some cases like Hong Kong, an area of This could be an address, a point of interest name, a city name, etc. Mapbox CLI SDK · MapboxDirections.swift (Objective-C and Swift); Mapbox Java SDK Reverse geocoding. get. /geocoding/v5/{endpoint}/{longitude},{latitude}.​json. Find Latitude and Longitude Address field - enter an address, city, state, place name, postal code or any other name for a location into this field, select "North America" or "Europe" from the region menu, and then click the find button to retrieve its latitude-longitude coordinate pair.

Comments
  • developer.apple.com/reference/corelocation/clgeocoder
  • See my answer in swift 4.1 Xcode 9.4.1. You can get even village name details also. stackoverflow.com/questions/16647996/…
  • i dont insert map in my project i just use this code for latitude and longitude
  • @A.Ali, based on this answer, you can use Google API easily without integrating maps, just using Alamofire to fire http request
  • You don't have to include other API's and network requests if your already using gps if he needs country short name is isoCountryCode you should look some deeper in Apples documentation not need to make network calls for that
  • Alamofire is indeed nice to make HTTP requests in Swift ;)
  • Suggesting the use of Google is probably not the best answer (unless you have some good investment for the app) . The Google APIs gives you the illusion of being free until you read the T&C carefully. There are usage restrictions as well so be careful with how you use it. If you are just trying to learn then by all means explore Google API, but I recommend learning Apple's CoreLocation first since it can do pretty much everything Google does (except a few advanced features) but with a little more coding (which is fun) and is free if you code it efficiently. Recommend @LeoDabus answer below.
  • thank you this very useful but how can i find country short names
  • developer.apple.com/reference/corelocation/clplacemark/… You can use isocountrycode instead of country
  • @LeoDabus, I would also like to know if you could help me figure out something else related to this. Say I am using your fetchCityAndCountry and a CLLogationManager to grab the user's current latitude and longitude. Replacing let location = CLLocation(latitude: -22.963451, longitude: -43.198242) with let latitude = locationManager.location?.coordinate.latitude and let longitude = locationManager.location?.coordinate.longitude and then creating a CLLocation object from there will not work because the locationManager hasn't had enough time to grab the location when fetch executes
  • You need to do that inside locationManager didUpdateLocations method
  • app-prefs:root=privacy&path=location/com.company.appname because of this line apple rejected the app
  • MKReverseGeocoder was deprecated years ago. You should use a CLGeocoder.
  • i dont insert map in my project i just use this code for latitude and longitude and i need country name to link i will use it