Dominik Sturm Dominik Sturm - 4 months ago 32
iOS Question

Unable Return String from CLGeocoder reverseGeocodeLocation

I want to write a function to reverse geocode a location and assign the resulting string into a variable. Following this post i've got something like this:

extension CLLocation {

func reverseGeocodeLocation(completion: (answer: String?) -> Void) {

CLGeocoder().reverseGeocodeLocation(self) {

if let error = $1 {
print("[ERROR] \(error.localizedDescription)")
return
}

if let a = $0?.last {
guard let streetName = a.thoroughfare,
let postal = a.postalCode,
let city = a.locality else { return }

completion(answer: "[\(streetName), \(postal) \(city)]")
}

}
}
}


For calling this function i've just got something like this:

location.reverseGeocodeLocation { answer in
print(answer)
}


But instead i want to assign the string value of
answer
to a variable and i don't know how to pass that data out of the closure. What is the best way to do something like this?

Rob Rob
Answer

The problem is that it runs asynchronously, so you can't return the value. If you want to update some property or variable, the right place to do that is in the closure you provide to the method, for example:

var geocodeString: String?

location.reverseGeocodeLocation { answer in
    geocodeString = answer
    // and trigger whatever UI or model update you want here
}

// but not here

The entire purpose of the closure completion handler pattern is that is the preferred way to provide the data that was retrieved asynchronously.