首页 > 解决方案 > 如何使用 API 调用数据更新视图

问题描述

我正在尝试使用从URLSession请求中收到的数据更新我的视图。

我可以使用以下命令将数据打印到控制台onAppear

struct HomeTab: View {

var body: some View {
    
    VStack(spacing: 1) {
        Text(//I want the data to show here)
        Spacer()
    }.padding()

   .onAppear {
    callDevices().getDevices { (response) in
        print(response.devices[0].parentRelations[0].displayName)
        }
    }
}

但我不知道如何在我的视图中实际显示数据?我希望在每个onAppear.

我怎样才能做到这一点?

这是我的模型:

struct Welcome: Codable {
    let devices: [Device]
}

// MARK: - Device
struct Device: Codable {
    let name, type, assignee: String
    let parentRelations: [ParentRelation]
}

// MARK: - ParentRelation
struct ParentRelation: Codable {
    let parent, displayName: String
}

和我的 API 类:

class callDevices {
    private var project_id: String = "redacted"
    func getDevices(completion: @escaping (Welcome) -> ()) {
        guard let url = URL(string: "https://redacted") else {return}
        
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("redacted", forHTTPHeaderField: "Authorization")
        
        
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            guard error == nil else {print(error!.localizedDescription); return }
            guard let data = data else {print("empty data"); return }

            let theData = try! JSONDecoder().decode(Welcome.self, from: data)
            DispatchQueue.main.async {
                completion(theData)
            }
            
        }
        .resume()
    }
}

标签: swiftswiftui

解决方案


忘记完成处理程序并利用Combine框架和@Published属性。

在您的班级中采用ObservableObject并声明一个@Published属性devices。将设备数组分配给闭包中的属性

import Combine

class CallDevices : ObservableObject {
    private var project_id: String = "redacted"
 
    @Published var devices = [Device]() 

    func getDevices() {
        guard let url = URL(string: "https://redacted") else {return}
        
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("redacted", forHTTPHeaderField: "Authorization")
        
        
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            guard error == nil else {print(error!.localizedDescription); return }
            // guard let data = data else {print("empty data"); return }

            let theData = try! JSONDecoder().decode(Welcome.self, from: data!)
            DispatchQueue.main.async {
                self.devices = theData.devices
            }
            
        }
        .resume()
    }
}

在视图中,在onAppearcall中声明对可观察类的引用getDevices()。视图将在修改后devices更新

struct HomeTab: View {

    @StateObject var callDevices = CallDevices()
    
    var body: some View {
        
        VStack(spacing: 1) {
            Text(callDevices.devices.first?.parentRelations.first?.displayName ?? "")
            Spacer()
        }.padding()
    
       .onAppear {
           callDevices.getDevices()  
       }
    }
}

推荐阅读