正在尝试显示 API 个要查看的结果

Trying to display API results to View

我的 API 调用完成后,正在尝试在视图中显示文本。我想我会在数据加载后将我想要的 API 结果 (foodDescription) 保存到一个变量,然后在视图中显示该变量。

我的猜测是我在 api 调用之前加载视图(或者我可能完全不相信我的猜测)。我也觉得我使用 DispatchQueue 不正确,也很乐意提供反馈。提前谢谢你。

API呼叫

 class FoodApiSearch{
        var foodDescription = ""
        //will search for user Input
        func searchFood(userItem: String){
           //calls api search
            guard let url = URL(string: "https://api.nal.usda.gov/fdc/v1/foods/search?query=\(userItem)&dataType=&pageSize=1&pageNumber=1&api_key=*****") else {return}
            
            URLSession.shared.dataTask(with: url) { (data, _,_) in
                let searchResults = try! JSONDecoder().decode(APISearchResults.self, from: data!)
                
                DispatchQueue.main.async {
                    for item in searchResults.foods{
                            self.foodDescription = item.foodDescription ?? "food not valid"
                            print(self.foodDescription)
                        }
                    }
            }
            .resume()
        }
    }

结构

  struct testA: View {
        //Textfield
        @State var userFoodInput = ""
        //will store api var of foodName
        @State var foodName = ""
        var body: some View {
                VStack{
                    TextField("enter first name", text: $userFoodInput)
                    Button("click me"){
                        //action
                
                        FoodApiSearch().searchFood(userItem: userFoodInput)
                       foodName =  FoodApiSearch().foodDescription
                    }
                    Text("You searched for " + foodName)
            }
        }
    }

因为 searchFood 是异步的,您不能只在后续行上分配 foodName = FoodApiSearch().foodDescription 并期望它 return 得到正确的结果。还有另一个问题:您正在创建 FoodApiSearch 的两个不同实例(每次键入 FoodApiSearch() 都是一个新实例)。

您可能希望将 FoodApiSearch 变成 ObservableObject@Published 属性。看起来像这样:

class FoodApiSearch : ObservableObject {
   @Published  var foodDescription = ""

   func searchFood(userItem: String) {

然后,您在 View 中使用 @StateObject 存储它的 单个实例 ,如果要显示结果,请使用 @Published 变量 -- 不要试图将它分配给本地变量 @State:

struct TestA: View {
        @State private var userFoodInput = ""
        @StateObject private var foodApi = FoodApiSearch()

        var body: some View {
                VStack{
                    TextField("enter first name", text: $userFoodInput)
                    Button("click me") {
                        foodApi.searchFood(userItem: userFoodInput)
                    }
                    if !foodApi.foodDescription.isEmpty {
                        Text(foodApi.foodDescription)
                    }
            }
        }
    }