Swift - Generate an Address Format from Reverse Geocoding

reverse geocoding ios swift 4
get address from latitude and longitude google map ios
geocodeaddressstring swift 4
get city name from latitude and longitude swift 3
'addressdictionary' was deprecated in ios 11.0: use @properties
mapkit reverse geocode
get address from latitude and longitude google map swift
xcode geolocation

I am trying to generate a Formatted Full address using CLGeocoder in Swift 3. I referred to this SO thread to get the code given below.

However, sometimes the app crashes with a 'nil' error at the line:

//Address dictionary
print(placeMark.addressDictionary ?? "")

Questions:

  1. How can I concatenate these values retrieved from the GeoCoder to form a full address? (Street + City + etc)
  2. How do I handle the nil error I get when the func is unable to find an address?

Full code:

func getAddress() -> String {
        var address: String = ""

        let geoCoder = CLGeocoder()
        let location = CLLocation(latitude: selectedLat, longitude: selectedLon)
        //selectedLat and selectedLon are double values set by the app in a previous process

        geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in

            // Place details
            var placeMark: CLPlacemark!
            placeMark = placemarks?[0]

            // Address dictionary
            //print(placeMark.addressDictionary ?? "")

            // Location name
            if let locationName = placeMark.addressDictionary!["Name"] as? NSString {
                //print(locationName)
            }

            // Street address
            if let street = placeMark.addressDictionary!["Thoroughfare"] as? NSString {
                //print(street)
            }

            // City
            if let city = placeMark.addressDictionary!["City"] as? NSString {
                //print(city)
            }

            // Zip code
            if let zip = placeMark.addressDictionary!["ZIP"] as? NSString {
                //print(zip)
            }

            // Country
            if let country = placeMark.addressDictionary!["Country"] as? NSString {
                //print(country)
            }

        })

        return address;
    } 

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)
              }
        })

    }

Converting Between Coordinates and User-Friendly Place Names , Swift; Objective-C You can create multiple geocoder objects and perform multiple conversions, but For example, if the user selects a location on a map, you might want to show the address at that location. Reverse geocoding a coordinate For example, passing a string of "100 Main St., USA" may return many results  Creating the User Interface. Open ReverseGeocodingViewController.swift and create five outlets as shown below. The text fields are used for entering the latitude and longitude. The application uses these values to reverse geocode the address of the location. The label displays the result of the geocoding operation.


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.

Reverse Geocoding With CLGeocoder, Open ReverseGeocodingViewController.swift and create five outlets The application uses these values to reverse geocode the address of the location. The reason is that not every country has, for example, the concept of  Four of these services require you to create an API key for reverse geocoding whereas one (DataScienceToolkit) offers the reverse geocoding directly using just syntax without the need for an API key. You can easily generate an API key by creating a free account and then use it with the proper syntax to reverse geocode lat-long to address.


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)

Forward Geocoding With CLGeocoder, Forward And Reverse Geocoding With Clgeocoder Initially, the functionality of the CLGeocoder class was limited to reverse geocoding addresses into coordinates. Open ForwardGeocodingViewController.swift and create six outlets as For this example, we only need the location property of the first  A geographic location to generate an address for. The coordiantes must be in WGS84 format. osm_type=[N|W|R] osm_id=<value> A specific OSM node(N), way(W) or relation(R) to return an address for. In both cases exactly one object is returned. The two input parameters cannot be used at the same time.


  1. For fixing the empty address issue, either you can use a class property to hold the appended value or you can use a closure to return the value back to the calling function
  2. For fixing the crash you need to avoid the force unwrapping of optionals

Using a closure you can do it like:

// Using closure
func getAddress(handler: (String) -> Void)
{
    var address: String = ""
    let geoCoder = CLGeocoder()
    let location = CLLocation(latitude: selectedLat, longitude: selectedLon)
    //selectedLat and selectedLon are double values set by the app in a previous process

    geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in

        // Place details
        var placeMark: CLPlacemark?
        placeMark = placemarks?[0]

        // Address dictionary
        //print(placeMark.addressDictionary ?? "")

        // Location name
        if let locationName = placeMark?.addressDictionary?["Name"] as? String {
            address += locationName + ", "
        }

        // Street address
        if let street = placeMark?.addressDictionary?["Thoroughfare"] as? String {
            address += street + ", "
        }

        // City
        if let city = placeMark?.addressDictionary?["City"] as? String {
            address += city + ", "
        }

        // Zip code
        if let zip = placeMark?.addressDictionary?["ZIP"] as? String {
            address += zip + ", "
        }

        // Country
        if let country = placeMark?.addressDictionary?["Country"] as? String {
            address += country
        }

       // Passing address back
       handler(address)
    })
}

You can call the method like:

getAddress { (address) in
    print(address)
}

Tutorial: Geocoding with Swift 4. - Enrico Piovesan, A guide to convert an address to a location point (latitude, longitude) using the iOS native SDK or the Google maps API 6 Create a geocoder using the iOS SDK CLGeocoder Check out the example source code on Github. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Learn more geocoder.geocodeAddressString no longer works with swift update today


To concatenate you can simply replace return address by this :

return "\(locationName), \(street), \(city), \(zip), \(country)"

Find places and addresses—ArcGIS Runtime SDK for iOS, I am trying to generate a Formatted Full address using CLGeocoder in Swift 3. I referred to this SO thread to get the code given below. Reverse-geocoding requests take a latitude and longitude value and find a user-readable address. Forward-geocoding requests take a user-readable address and find the corresponding latitude and longitude value. Forward-geocoding requests may also return additional information about the specified location, such as a point of interest or building at that location. For both types of request, the results are returned using a CLPlacemark object. In the case of forward-geocoding requests, multiple


Geocoding and Reverse Geocoding, I am trying to generate a Formatted Full address using CLGeocoder in Swift 3. I referred to this SO thread to get the code given below. However, sometimes the  You need to use reverse geocoding of map kit. 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.


Reverse Geocoding | Maps SDK for iOS, Find places and addresses This topic describes how to build an iOS on a map to real world addresses (also known as reverse geocoding). layout of your application changes, for example, when the device is rotated. removeAllGraphics() } if self.locator == nil { //Create the AGSLocator pointing to the geocode service  Reverse Geocoding Convert Lat Long to Address. Reverse geocoding is the process to convert the latitude and longitude coordinates to a readable address. Type the lat long coordinates and press Convert button. Reverse geocoded address will shown below. Also the municipality, subdivision and country name can be found.


Geocoding and reverse geocoding APIs from SDK for iOS allow application It encompasses everything about an address or a point on the map. The following example shows how to create and use an NMAReverseGeocodeRequest :. Geocoding can be forward, when we obtain the geographical coordinates ( latitude and longitude) from other location data such as postal addresses, or reverse, when we obtain the address of a location by having the latitude and longitude as inputs.