Essentially I am converting string addresses into CLLocationCoordinate2D, to acheive this I am looping through an array of addresses that are in a specific order I need to keep the same, but when the escaping async function runs it changes the order of the array addresses as a result, how can async/await be used to achieve this result?
Resources like this are helpful but I am still struggling to understand the proper way to implement. https://www.biteinteractive.com/swift-5-5-asynchronous-looping-with-async-await/
func getLocation(from address: String, completion: @escaping (_ location: CLLocationCoordinate2D?)-> Void) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
guard let placemarks = placemarks,
let location = placemarks.first?.location?.coordinate
else {
completion(nil)
return
}
completion(location)
}
}
let addresses = ["SAUGET, IL", "SAN FRANCISCO, CA", "SAINT LOUIS, MO"]
for address in addresses {
print(address)
getLocation(from: address) { location in
//printing not the same order as the order the loop is sending them in.
print("address: \(address)")
}
}
CodePudding user response:
Just make an rendition that uses the async-await rendition of geocodeAddressString
:
func getCoordinate(from address: String) async throws -> CLLocationCoordinate2D {
let geocoder = CLGeocoder()
guard let location = try await geocoder.geocodeAddressString(address)
.compactMap( { $0.location } )
.first(where: { $0.horizontalAccuracy >= 0 } )
else {
throw CLError(.geocodeFoundNoResult)
}
return location.coordinate
}
Then you can do:
func lookupCoordinates() async throws {
let addresses = ["SAUGET, IL", "SAN FRANCISCO, CA", "SAINT LOUIS, MO", "NEW YORK, NY"]
for address in addresses {
let coordinate = try await getCoordinate(from: address)
print("address: \(coordinate)")
}
}
Unrelated, we should note that the geocodeAddressString
documentation warns us:
After initiating a forward-geocoding request, do not attempt to initiate another reverse- or forward-geocoding request.
The CLGeocoder
documentation also warns us:
Geocoding requests are rate-limited for each app, so making too many requests in a short period of time may cause some of the requests to fail. ... Send at most one geocoding request for any one user action.
Just a FYI.