我试图通过单击“获取”按钮从api获取数据,并通过ScrollView中的ForEach循环显示它们。
我正在使用MVVM模型。提取本身发生在ObservableObject类中。
不幸的是,ScrollView不显示内容。如果我使用列表而不是ScrollView,则可以正常工作。
你知道我在这里想念什么吗?
非常感谢您的帮助!
import SwiftUI
struct Photo: Identifiable, Decodable {
let id = UUID()
let title: String
}
class ContentViewModel: ObservableObject {
let api = "https://jsonplaceholder.typicode.com/photos"
@Published var photos: [Photo] = []
func fetchData() {
print("Fetching started")
guard let url = URL(string: api) else { return }
URLSession.shared.dataTask(with: url) { data, _, _ in
DispatchQueue.main.async {
self.photos = try! JSONDecoder().decode([Photo].self, from: data!)
print("Fetching successfull. Fetched \(self.photos.count) photos.")
}
}.resume()
}
}
struct ContentView: View {
@ObservedObject var contentVM = ContentViewModel()
var body: some View {
NavigationView {
ScrollView {
ForEach(self.contentVM.photos) { photo in
Text(photo.title)
}
}
.navigationBarTitle("Home")
.navigationBarItems(trailing: Button(action: {
self.contentVM.fetchData()
}, label: {
Text("Fetch")
}))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
答案 0 :(得分:1)
您什么都没错过,我认为问题在于渲染内容。即使在您的示例中,数据仍显示在真实设备(iPhone 7 iOS 13.1.1)上,但延迟很长。尝试使用较少的内容或帮助ScrollView
进行对齐。我尝试了这一点-在设备上运行速度更快,但仅在设备上运行:
class ContentViewModel: ObservableObject {
let api = "https://jsonplaceholder.typicode.com/photos"
@Published var photos: [Photo] = []
@Published var first100Photos: [Photo] = []
func fetchData() {
print("Fetching started")
guard let url = URL(string: api) else { return }
URLSession.shared.dataTask(with: url) { data, _, _ in
DispatchQueue.main.async {
self.photos = try! JSONDecoder().decode([Photo].self, from: data!)
for index in 0...100 {
self.first100Photos.append(self.photos[index])
}
print("Fetching successfull. Fetched \(self.photos.count) photos.")
}
}.resume()
}
}
struct ContentView: View {
@ObservedObject var contentVM = ContentViewModel()
var body: some View {
NavigationView {
ScrollView(.vertical) {
VStack {
ForEach(self.contentVM.first100Photos) { photo in
Text(photo.title)
}
}
}
.navigationBarTitle("Home")
.navigationBarItems(trailing: Button(action: {
self.contentVM.fetchData()
}, label: {
Text("Fetch")
}))
}
}
}