Swift - Generate an Address Format from Reverse Geocoding
func getAddressFromLatLon(pdblLatitude: String, withLongitude pdblLongitude: String) { var center : CLLocationCoordinate2D = CLLocationCoordinate2D() let lat: Double = Double("\(pdblLatitude)")! //21.228124 let lon: Double = Double("\(pdblLongitude)")! //72.833770 let ceo: CLGeocoder = CLGeocoder() center.latitude = lat center.longitude = lon let loc: CLLocation = CLLocation(latitude:center.latitude, longitude: center.longitude) ceo.reverseGeocodeLocation(loc, completionHandler: {(placemarks, error) in if (error != nil) { print("reverse geodcode fail: \(error!.localizedDescription)") } let pm = placemarks! as [CLPlacemark] if pm.count > 0 { let pm = placemarks![0] print(pm.country) print(pm.locality) print(pm.subLocality) print(pm.thoroughfare) print(pm.postalCode) print(pm.subThoroughfare) var addressString : String = "" if pm.subLocality != nil { addressString = addressString + pm.subLocality! + ", " } if pm.thoroughfare != nil { addressString = addressString + pm.thoroughfare! + ", " } if pm.locality != nil { addressString = addressString + pm.locality! + ", " } if pm.country != nil { addressString = addressString + pm.country! + ", " } if pm.postalCode != nil { addressString = addressString + pm.postalCode! + " " } print(addressString) } }) }
Formatting addresses is hard because each country has its own format.
With a few lines of code, you can get the correct address format for each country and let Apple handle the differences.
Since iOS 11, you can get a Contacts framework address:
extension CLPlacemark { @available(iOS 11.0, *) open var postalAddress: CNPostalAddress? { get }}
This extension is part of the Contacts
framework.This means, this feature is invisible to you in the XCode
code completion until you do
import Contacts
With this additional import, you can do something like
CLGeocoder().reverseGeocodeLocation(location, preferredLocale: nil) { (clPlacemark: [CLPlacemark]?, error: Error?) in guard let place = clPlacemark?.first else { print("No placemark from Apple: \(String(describing: error))") return } let postalAddressFormatter = CNPostalAddressFormatter() postalAddressFormatter.style = .mailingAddress var addressString: String? if let postalAddress = place.postalAddress { addressString = postalAddressFormatter.string(from: postalAddress) }}
and get the address formatted in the format for the country in the address.
The formatter even supports formatting as an attributedString.
Prior to iOS 11, you can convert CLPlacemark
to CNPostalAddress
yourself and still can use the country specific formatting of CNPostalAddressFormatter
.
This is my code for swift 3
func getAdressName(coords: CLLocation) { CLGeocoder().reverseGeocodeLocation(coords) { (placemark, error) in if error != nil { print("Hay un error") } else { let place = placemark! as [CLPlacemark] if place.count > 0 { let place = placemark![0] var adressString : String = "" if place.thoroughfare != nil { adressString = adressString + place.thoroughfare! + ", " } if place.subThoroughfare != nil { adressString = adressString + place.subThoroughfare! + "\n" } if place.locality != nil { adressString = adressString + place.locality! + " - " } if place.postalCode != nil { adressString = adressString + place.postalCode! + "\n" } if place.subAdministrativeArea != nil { adressString = adressString + place.subAdministrativeArea! + " - " } if place.country != nil { adressString = adressString + place.country! } self.lblPlace.text = adressString } } } }
You can esaily call above funcation like:
let cityCoords = CLLocation(latitude: newLat, longitude: newLon)cityData(coord: cityCoords)