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) } }
Latitude and longitude are a pair of numbers (coordinates) used to describe a position on the plane of a geographic coordinate system. The numbers are in decimal degrees format and range from -90 to 90 for latitude and -180 to 180 for longitude. For example, Washington DC has a latitude 38.8951 and longitude -77.0364 .
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 }
edit/update:
iOS 11 or later CLPlacemark
has a postalAddress
property. You can import Contacts
framework and use CNPostalAddressFormatter
's string(from:)
method to get a localized formatted address. You can also extend CLPlacemark and add some computed properties to better describe some of its properties:
import MapKit import Contacts extension CLPlacemark { /// street name, eg. Infinite Loop var streetName: String? { thoroughfare } /// // eg. 1 var streetNumber: String? { subThoroughfare } /// city, eg. Cupertino var city: String? { locality } /// neighborhood, common name, eg. Mission District var neighborhood: String? { subLocality } /// state, eg. CA var state: String? { administrativeArea } /// county, eg. Santa Clara var county: String? { subAdministrativeArea } /// zip code, eg. 95014 var zipCode: String? { postalCode } /// postal address formatted @available(iOS 11.0, *) var postalAddressFormatted: String? { guard let postalAddress = postalAddress else { return nil } return CNPostalAddressFormatter().string(from: postalAddress) } }
extension CLLocation { func placemark(completion: @escaping (_ placemark: CLPlacemark?, _ error: Error?) -> ()) { CLGeocoder().reverseGeocodeLocation(self) { completion($0?.first, $1) } } }
Usage:
let location = CLLocation(latitude: 37.331676, longitude: -122.030189) location.placemark { placemark, error in guard let placemark = placemark else { print("Error:", error ?? "nil") return } print(placemark.postalAddressFormatted ?? "") }
This will print
1 Infinite Loop
Cupertino CA 95014
United States
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With