swiftui - SwiftUI:如何让服务器数据显示?
问题描述
场景:从服务器访问数据(可变大小)并显示它。在这种情况下,一系列国家。
在进入此视图(或之前)时,应调用一次 (1)服务器访问。
观察:我可以通过发布者中的调试器和打印语句查看数据。
问题:数据不显示在视图中。
以下是整个代码(简化为通过游乐场对一系列国家/地区的简单请求)。
请随意剪切/粘贴到操场上。
它应该按预期运行,但不显示任何数据。
解决方案?
import Combine
import SwiftUI
import PlaygroundSupport
// ---------------------------------------------------------------------------
var cancellables: Set<AnyCancellable> = []
struct VaccinesDataView: View {
@State private var appleData: [String]?
@StateObject var appleCountries = AppleCountries()
var body: some View {
Form {
Section(header: VStack(alignment: .leading) {
Text("Apple Data")
}) {
if let vacData = appleData {
ForEach(vacData, id: \.self) { source in
HStack {
Text(source)
.font(.title)
}
}
}
}
.navigationBarTitle("Vaccines", displayMode: .inline)
}.onAppear {
self.appleCountries.getData()
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
// =====================================================================================================
class AppleCountries: ObservableObject {
@Published var appleData: [String]?
func getData() {
let appleURL = URL(string: "https://disease.sh/v3/covid-19/apple/countries")!
let remoteDataPublisher = URLSession.shared.dataTaskPublisher(for: appleURL)
.map(\.data)
.receive(on: DispatchQueue.main)
.decode(type: [String].self, decoder: JSONDecoder())
.print("Apples: ")
remoteDataPublisher
.eraseToAnyPublisher()
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Publisher Finished")
case let .failure(anError):
Swift.print("\nReceived error: ", anError)
}
}, receiveValue: { someValue in
self.appleData = someValue
print("appleData: \(String(describing: self.appleData))")
}).store(in: &cancellables)
}
}
PlaygroundPage.current.setLiveView(VaccinesDataView())
提示:当我只想要一 (1) 个时,我注意到对服务器的重复访问。
服务器访问是通过.onAppear ()可能被多次调用的。
Apples: : receive subscription: (Decode)
Apples: : request unlimited
Apples: : receive subscription: (Decode)
Apples: : request unlimited
Apples: : receive subscription: (Decode)
Apples: : request unlimited
Apples: : receive subscription: (Decode)
Apples: : request unlimited
Apples: : receive value: (["Albania", "Argentina", "Australia", "Austria", "Belgium", "Brazil", "Bulgaria", "Cambodia", "Canada", "Chile", "Colombia", "Croatia", "Czechia", "Denmark", "Egypt", "Estonia", "Finland", "France", "Germany", "Greece", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Ireland", "Israel", "Italy", "Japan", "Latvia", "Lithuania", "Luxembourg", "Macao", "Malaysia", "Mexico", "Morocco", "Netherlands", "New Zealand", "Norway", "Philippines", "Poland", "Portugal", "S. Korea", "Romania", "Russia", "Saudi Arabia", "Serbia", "Singapore", "Slovakia", "Slovenia", "South Africa", "Spain", "Sweden", "Switzerland", "Taiwan", "Thailand", "Turkey", "Ukraine", "UAE", "UK", "USA", "Uruguay", "Vietnam"])
appleData: Optional(["Albania", "Argentina", "Australia", "Austria", "Belgium", "Brazil", "Bulgaria", "Cambodia", "Canada", "Chile", "Colombia", "Croatia", "Czechia", "Denmark", "Egypt", "Estonia", "Finland", "France", "Germany", "Greece", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Ireland", "Israel", "Italy", "Japan", "Latvia", "Lithuania", "Luxembourg", "Macao", "Malaysia", "Mexico", "Morocco", "Netherlands", "New Zealand", "Norway", "Philippines", "Poland", "Portugal", "S. Korea", "Romania", "Russia", "Saudi Arabia", "Serbia", "Singapore", "Slovakia", "Slovenia", "South Africa", "Spain", "Sweden", "Switzerland", "Taiwan", "Thailand", "Turkey", "Ukraine", "UAE", "UK", "USA", "Uruguay", "Vietnam"])
Apples: : receive finished
Publisher Finished
Apples: : receive value: (["Albania", "Argentina", "Australia", "Austria", "Belgium", "Brazil", "Bulgaria", "Cambodia", "Canada", "Chile", "Colombia", "Croatia", "Czechia", "Denmark", "Egypt", "Estonia", "Finland", "France", "Germany", "Greece", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Ireland", "Israel", "Italy", "Japan", "Latvia", "Lithuania", "Luxembourg", "Macao", "Malaysia", "Mexico", "Morocco", "Netherlands", "New Zealand", "Norway", "Philippines", "Poland", "Portugal", "S. Korea", "Romania", "Russia", "Saudi Arabia", "Serbia", "Singapore", "Slovakia", "Slovenia", "South Africa", "Spain", "Sweden", "Switzerland", "Taiwan", "Thailand", "Turkey", "Ukraine", "UAE", "UK", "USA", "Uruguay", "Vietnam"])
appleData: Optional(["Albania", "Argentina", "Australia", "Austria", "Belgium", "Brazil", "Bulgaria", "Cambodia", "Canada", "Chile", "Colombia", "Croatia", "Czechia", "Denmark", "Egypt", "Estonia", "Finland", "France", "Germany", "Greece", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Ireland", "Israel", "Italy", "Japan", "Latvia", "Lithuania", "Luxembourg", "Macao", "Malaysia", "Mexico", "Morocco", "Netherlands", "New Zealand", "Norway", "Philippines", "Poland", "Portugal", "S. Korea", "Romania", "Russia", "Saudi Arabia", "Serbia", "Singapore", "Slovakia", "Slovenia", "South Africa", "Spain", "Sweden", "Switzerland", "Taiwan", "Thailand", "Turkey", "Ukraine", "UAE", "UK", "USA", "Uruguay", "Vietnam"])
Apples: : receive finished
Publisher Finished
...
...
...
解决方案
您不需要额外的状态appleData
- 它没有填充 -appleCountries
直接使用如下。
使用 Xcode 12.1 / iOS 14.1 测试
struct VaccinesDataView: View {
@StateObject var appleCountries = AppleCountries()
var body: some View {
Form {
Section(header: VStack(alignment: .leading) {
Text("Apple Data")
}) {
if let vacData = appleCountries.appleData { // !!
ForEach(vacData, id: \.self) { source in
HStack {
Text(source)
.font(.title)
}.onAppear {
appleCountries.getData()
}
}
}
}
.navigationBarTitle("Vaccines", displayMode: .inline)
}.onAppear {
self.appleCountries.getData()
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
推荐阅读
- ubuntu - Windows 7 上的 Oracle VM 虚拟机启动错误:lvmetad 尚未激活
- flask - 烧瓶对excel文件的响应给出损坏的excel文件
- r - 如何为大型数据集创建唯一向量
- java - 如何处理组中的所有已读项目,而不是一对一处理?
- javascript - 如何在javascript中使用多个键进行分组
- python - 熊猫和绘图图
- php - 如何同时运行两个 foreach 循环(laravel)
- c++ - 性能差异调试与发布
- javascript - 有没有一种 jQuery 方法来制作出现在不会破坏响应性的表格单元格的左下方?
- java - 对话框类中的公共命令 showPopupDialog(Component c) 引发错误