我有一个函数,它调用两种类型的api请求来获取我的应用程序中需要的一堆数据。在函数中,我请求位置,然后在响应中为每个位置请求一个不同的请求,以获取该特定位置的详细信息。 (例如,如果请求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() }
[在获得所有我要的数据之后(甚至当数据传入时),我想将其附加到我在SceneDelegate.swift文件中设置的@EnvironmentObject(数组)中。我在应用程序的多个位置使用了数据,因此@EnvironmentObject充当“真理的来源”。
我尝试使用下面的代码完成此操作,但仍然会收到错误-“不允许从后台线程发布更改;请确保在模型上从主线程发布值(通过诸如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吗?
有人知道为什么我上面的代码片段使一切正常吗?
Id只是想了解我在做什么,如果有人发现了这个,也许有人可以学到一些东西
我有一个函数,它调用两种类型的api请求来获取我的应用程序中需要的一堆数据。在函数中,我请求一个位置,然后对于响应中的每个位置,我都做出不同的...
有一些您无法通过后台线程成功完成的事情。其中一些(例如UIKit内容更改)不会产生错误,但是会静默失败,这更糟。您很幸运收到了相对具体的错误消息。
我尝试在我的第二个api请求中使用此代码段,但它解决了我的问题,尽管我不明白为什么需要这样做