Converting a city name to coordinates in Swift

Viewed 2696

I saw few questions on SO but all of them are old in Swift 2. I got this function from Apple website to convert a city name to latitude and longitude but I am not sure what the function will return (since there is nothing after return statement) and what should I pass. Would someone explain it a lil or show me how to use it please.

func getCoordinate( addressString : String, 
        completionHandler: @escaping(CLLocationCoordinate2D, NSError?) -> Void ) {
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(addressString) { (placemarks, error) in
        if error == nil {
            if let placemark = placemarks?[0] {
                let location = placemark.location!

                completionHandler(location.coordinate, nil)
                return
            }
        }

        completionHandler(kCLLocationCoordinate2DInvalid, error as NSError?)
    }
}
2 Answers

You can do it as follow:

import CoreLocation

func getCoordinateFrom(address: String, completion: @escaping(_ coordinate: CLLocationCoordinate2D?, _ error: Error?) -> () ) {
    CLGeocoder().geocodeAddressString(address) { completion($0?.first?.location?.coordinate, $1) }
}

Usage:

let address = "Rio de Janeiro, Brazil"

getCoordinateFrom(address: address) { coordinate, error in
    guard let coordinate = coordinate, error == nil else { return }
    // don't forget to update the UI from the main thread
    DispatchQueue.main.async {
        print(address, "Location:", coordinate) // Rio de Janeiro, Brazil Location: CLLocationCoordinate2D(latitude: -22.9108638, longitude: -43.2045436)
    }

}

Doing an asynchronous operation like fetching the coordinates of a city can't return a value as the function result. You have to make the call, go about your business, and wait for it to call your completion handler. That what the parameter completionHandler is in the code above. You pass in a closure (a block of code) to be executed once the results are ready. You'd use it like this:

getCoordinate(addressString: someString) { coordinate, error in
  if error != nil {
    //display error
    return
  } else {
    //at this point `coordinate ` contains a valid coordinate. 
    //Put your code to do something with it here
    print("resulting coordinate = (\(coordinate.latitude),\(coordinate.longitude))")
  }
}

Note that for Swift 3, you'd make your function throw rather than returning either a result or an error.

Related