У меня есть функция, которая вызывает 2 типа запросов API, чтобы получить кучу данных, которые мне нужны в моем приложении. В функции я делаю запрос местоположений, затем для каждого местоположения в ответе я делаю разные запросы, чтобы получить подробную информацию об этом конкретном c местоположении. (например, если запрос 1 возвращает 20 местоположений, мой второй запрос вызывается 20 раз, по одному разу для каждого местоположения)
Мой код функции здесь:
func requestAndCombineGData(location: CLLocation, radius: Int) {
// Clears map of markers
self.mapView.clear()
// Calls 'Nearby Search' request
googleClient.getGooglePlacesData(location: location, withinMeters: radius) { (response) in
print("Made Nearby Search request. Returned response here:", response)
// loops through each result from the above Nearby Request response
for location in response.results {
// Calls 'Place Details' request
self.googleClient.getGooglePlacesDetailsData(place_id: location.place_id) { (detailsResponse) in
print("GMV returned - detailsResponse.result - ", detailsResponse.result)
}
}
}
}
Функции запроса, на которые я ссылаюсь выше, здесь :
func getGooglePlacesData(location: CLLocation, withinMeters radius: Int, using completionHandler: @escaping (GooglePlacesResponse) -> ()) {
for category in categoriesArray {
let url = googlePlacesNearbyDataURL(forKey: googlePlacesKey, location: location, radius: radius, type: category)
let task = session.dataTask(with: url) { (responseData, _, error) in
if let error = error {
print(error.localizedDescription)
return
}
guard let data = responseData, let response = try? JSONDecoder().decode(GooglePlacesResponse.self, from: data) else {
print("Could not decode JSON response")
completionHandler(GooglePlacesResponse(results:[]))
return
}
if response.results.isEmpty {
print("GC - response returned empty", response)
} else {
print("GC - response contained content", response)
completionHandler(response)
}
}
task.resume()
}
}
func getGooglePlacesDetailsData(place_id: String, using completionHandler: @escaping (GooglePlacesDetailsResponse) -> ()) {
let url = googlePlacesDetailsURL(forKey: googlePlacesKey, place_ID: place_id)
let task = session.dataTask(with: url) { (responseData, _, error) in
if let error = error {
print(error.localizedDescription)
return
}
guard let data = responseData, let detailsResponse = try? JSONDecoder().decode(GooglePlacesDetailsResponse.self, from: data) else {
print("Could not decode JSON response. responseData was: ", responseData)
return
}
print("GPD response - detailsResponse.result: ", detailsResponse.result)
completionHandler(detailsResponse)
}
task.resume()
}
После того, как я получу все данные, которые я запрашиваю (или даже когда данные поступают), я хотел бы добавить его в @EnvironmentObject (массив), который я настроил в моем SceneDelegate.swift файл. Я использую данные в нескольких местах в моем приложении, поэтому @EnvironmentObject служит «источником правды».
Я пытался выполнить это, используя приведенный ниже код, но продолжаю получать ошибку - "Публикация изменений из фоновых потоков не допускается; не забудьте опубликовать sh значения из основного потока (через операторы, такие как receive (on :)) при обновлении модели. "
func requestAndCombineGData(location: CLLocation, radius: Int) {
// Clears map of markers
self.mapView.clear()
// Calls 'Nearby Search' request
googleClient.getGooglePlacesData(location: location, withinMeters: radius) { (response) in
print("Made Nearby Search request. Returned response here:", response)
// loops through each result from the above Nearby Request response
for location in response.results {
// Calls 'Place Details' request
self.googleClient.getGooglePlacesDetailsData(place_id: location.place_id) { (detailsResponse) in
print("GMV returned - detailsResponse.result - ", detailsResponse.result)
// THIS IS WHERE I TRY TO UPDATE MY @ENVIROMETOBJECT
self.venueData.venuesdataarray.append(detailsRespose.result)
}
}
}
}
Я считаю, что мне нужно чтобы убедиться, что запросы завершены, ТОГДА попробуйте обновить мой @EnvironmentObject, но я не знаю, как это сделать.
РЕДАКТИРОВАТЬ - предоставляя мою структуру VenueData, как было запрошено в комментариях:
struct VenueData : Identifiable {
var id = UUID()
var name : String
var geometry : Location?
var rating : String?
var price_level : String?
var types : [String]?
var formatted_address : String?
var formatted_phone_number : String?
var website : String?
var photo_reference : String?
enum CodingKeysDetails : String, CodingKey {
case geometry = "geometry"
case name = "name"
case rating = "rating"
case price_level = "price_level"
case types = "types"
case opening_hours = "opening_hours"
case formatted_address = "formatted_address"
case formatted_phone_number = "formatted_phone_number"
case website = "website"
}
// Location struct
struct Location : Codable {
var location : LatLong
enum CodingKeys : String, CodingKey {
case location = "location"
}
// LatLong struct
struct LatLong : Codable {
var latitude : Double
var longitude : Double
enum CodingKeys : String, CodingKey {
case latitude = "lat"
case longitude = "lng"
}
}
}
}
class VenueDataArray: ObservableObject {
@Published var venuesdataarray : [VenueData] = [
VenueData(name: "test_name")
]
}
Редактирование решения - я попытался использовать этот фрагмент кода во втором запросе API, и это решило мою проблему, хотя я не понимаю, почему мне нужно это сделать
DispatchQueue.main.async {
self.venueData.venuesdataarray.append(RESPONSE_DETAILS_HERE)
}
Изначально я спрашивал: кто-нибудь знает, как я могу обновить мой @EnvironmentObject после завершения всех запросов?
Кто-нибудь знает, почему фрагмент кода у меня есть? Он заставляет все работать?
Мне бы просто хотелось понять, что я делаю, и, может быть, кто-то мог бы что-то узнать, если бы нашел это