首页 > 解决方案 > SwiftUI 在 GET 请求后显示 JSON 数据

问题描述

我知道这是典型的并发问题,但我是 Swift 新手,我觉得我已经阅读了所有相关的博客文章。我知道我正在正确获取数据,因为它显示在我的控制台中,但我无法让它显示在我的模拟器中。我相信这是因为我在加载数据之前显示 UI。

在我 100% 获取所有数据如何显示数据。我将添加控制台的相关代码和屏幕截图。对不起,如果这是一个“基本”问题。

在此处输入图像描述

在此处输入图像描述

结构

struct Welcome: Decodable, Identifiable {
    var id: Int?
    var readings: [Reading]?
    var include_maintenance_recommendations: Bool?
    var pool_volume: Int?
    var created_at, updated_at: String?
}

struct Reading: Decodable {
    var analyte: String?
    var value: String?
}

用户界面

var results = Welcome()

struct ContentView: View {
    @State var res = Welcome()
    var body: some View {
         Text(results.created_at ?? "N/A")
             .onAppear(){
                fetchResults().getData {(res) in
                    self.res = res
             }
         }
    }
}

获取函数

class fetchResults{
func getData(completion: @escaping (Welcome) -> ()){
    print("Fetch")

    let parameters = "{  \"pool_volume\": 10000,  \"readings\": [    {      \"analyte\": \"fc\",      \"value\": 1.6    },    {      \"analyte\": \"ph\",      \"value\": 7.3    }  ]}"
    let postData = parameters.data(using: .utf8)
    var request = URLRequest(url: URL(string: "https://www.biolabhydra.com/api/v3/water_tests")!,timeoutInterval: Double.infinity)
    request.addValue("Basic ***********************", forHTTPHeaderField: "Authorization")
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("csrftoken=***********************", forHTTPHeaderField: "Cookie")
    request.httpMethod = "POST"
    request.httpBody = postData

    let task = URLSession.shared.dataTask(with: request) { (data, _, _) in
        let resultList = try! JSONDecoder().decode(Welcome.self, from: data!)
                        print(" ")
                        print("ID: \(resultList.id ?? 111)")
                        print("VOLUME: \(resultList.pool_volume ?? 111)")
                        print("RECOMMENDATIONS: \(resultList.include_maintenance_recommendations ?? true)")
                        print("CREATD AT: \(resultList.created_at ?? "N/A")")
                        print("UPDATED AT: \(resultList.updated_at ?? "N/A")")
                        print("READINGS: \(String(describing: resultList.readings))")
                        print(" ")
        print("SUCCESS: Got data - \(data! )")
    }
    task.resume()
}
    
}

标签: jsonswiftconcurrencyswiftui

解决方案


  1. 使用局部属性而不是全局变量
struct ContentView: View {
    @State var res = Welcome()
    var body: some View {
         Text(res.created_at ?? "N/A")      // << here !!
             .onAppear(){
                fetchResults().getData {(res) in
                    self.res = res
             }
         }
    }
}
  1. 解码数据后添加回调
    let task = URLSession.shared.dataTask(with: request) { (data, _, _) in
        let result = try! JSONDecoder().decode(Welcome.self, from: data!)
                        print(" ")
                        print("ID: \(resultList.id ?? 111)")
                        print("VOLUME: \(resultList.pool_volume ?? 111)")
                        print("RECOMMENDATIONS: \(resultList.include_maintenance_recommendations ?? true)")
                        print("CREATD AT: \(resultList.created_at ?? "N/A")")
                        print("UPDATED AT: \(resultList.updated_at ?? "N/A")")
                        print("READINGS: \(String(describing: resultList.readings))")
                        print(" ")
        print("SUCCESS: Got data - \(data! )")
        
        DispatchQueue.main.async {
           completion(result)           // << here !!
        }
    }

推荐阅读