Good evening, after spending weeks trying to figure this out, I am looking for some guidance. I am trying to get a coordinate object to return and then go into a compact map. The function is working, because when I do a print, I can see it, but when the return happens, its blank. A completion handler will not work for me in this case, due to the function needed to return in order to update the data in the compact map.
Hopefully this will explain well enough:
public func findPlaces(
query: String,
completion: @escaping (Result<[Place], Error>) -> Void
) {
let filter = GMSAutocompleteFilter()
//filter.types = ["geocode", ]
filter.countries = ["US"]
client.findAutocompletePredictions(
fromQuery: query,
filter: filter,
sessionToken: nil
) { [self] results, error in
guard let results = results, error == nil else {
completion(.failure(PlacesError.failedToFind))
return
}
if results.isEmpty {
var places: [Place] = []
let noPlace = Place(name: "No results", identifier: "", detail: "", coords: PlaceCoords(withCoords: CLLocationCoordinate2D()), fullAddress: "")
places.append(noPlace)
completion(.success(places))
} else {
let places: [Place] = results.compactMap({
Place(
name: $0.attributedPrimaryText.string,
identifier: $0.placeID,
detail: Utils.shared.removeCountryFromPlace(string: $0.attributedFullText.string),
coords: PlaceCoords(withCoords: resolveLocation1(place: $0.placeID)), <---NEED A LOCATION COORDINATE HERE, THIS IS WHAT I AM TRYING TO RETURN
fullAddress: $0.attributedFullText.string
)
})
completion(.success(places))
}
}
}
This is the function that is working, meaning that it is getting the coordinate object, but it won't return. If I return inside the {} it gives me a void error.
public func resolveLocation1(place: String) -> CLLocationCoordinate2D {
var returnCoord = CLLocationCoordinate2D()
client.fetchPlace(fromPlaceID: place, placeFields: .coordinate, sessionToken: nil) { googlePlace, error in
guard let googlePlace = googlePlace, error == nil else { return }
let coordinate = CLLocationCoordinate2D(latitude: googlePlace.coordinate.latitude,longitude: googlePlace.coordinate.longitude) <-- PRINT HERE WORKS AND SHOWS A COORDINATE
returnCoord = coordinate <-- PRINT HERE WORKS AND SHOWS COORDINATE
}
print("Returned coord: \(returnCoord)") <-- BLANK AND SHOWS NOTHING
return returnCoord
}
Very last, I did write the same function with a completion handler, and when you run it by itself, it works and returns an object as expected. But, this is useless to me, because I cannot use this with in the compact map.
public func resolveLocation(
for place: String,
completion: @escaping (Result<CLLocationCoordinate2D, Error>) -> Void
) {
client.fetchPlace(fromPlaceID: place,
placeFields: .coordinate,
sessionToken: nil
) { googlePlace, error in
guard let googlePlace = googlePlace, error == nil else {
completion(.failure(PlacesError.failedToGetCoordinates))
return
}
let coordinate = CLLocationCoordinate2D(
latitude: googlePlace.coordinate.latitude,
longitude: googlePlace.coordinate.longitude
)
completion(.success(coordinate))
}
}
Any tips or advice would be much appreciated, I am just drawing a blank on what I am doing wrong.
*****EDIT 8-23-23 *****
So tonight, I took the advice and tried to convert the function to async, but it seems not to work correctly in a compactMap. I just learned Swift, but am very new to async/await in swift.
I added await the line where I called resolveLocation1
Place(
name: $0.attributedPrimaryText.string,
identifier: $0.placeID,
detail: Utils.shared.removeCountryFromPlace(string: $0.attributedFullText.string),
coords: PlaceCoords(withCoords: await resolveLocation1(place: $0.placeID)), <---AWAIT ADDED HERE
fullAddress: $0.attributedFullText.string
)
})
I am sure there are several ways to do this, but refactoring the function for async, it added async throws
before the return part. Also, this is now throwing an error, which says: Cannot pass function of type '(GMSAutocompletePrediction) async -> Place?' to parameter expecting synchronous function type
When I add await to this line: await client.fetchPlace(fromPlaceID: place, placeFields: .coordinate, sessionToken: nil) { googlePlace, error in
it tells me No 'async' operations occur within 'await' expression. After I remove that, I still have the error above.
I am looking for some pointers as to how to make this function work correctly in the compactMap. If there is a better solution, I am open to that as well. But I need to get the data in the results, each "row" of place id's to get the coordinates.