swift - 如何使用 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()
}
}
解决方案
忘记完成处理程序并利用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()
}
}
在视图中,在onAppear
call中声明对可观察类的引用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()
}
}
}