【发布时间】:2020-07-06 00:03:59
【问题描述】:
我有一个视图,它以滚动视图显示从 API 加载的几张照片。我想推迟获取图像,直到显示视图。我的观点,简化看起来像这样:
struct DetailView : View {
@ObservedObject var viewModel: DetailViewModel
init(viewModel: DetailViewModel) {
self.viewModel = viewModel
}
var body: some View {
GeometryReader { geometry in
ZStack {
Color("peachLight").edgesIgnoringSafeArea(.all)
if self.viewModel.errorMessage != nil {
ErrorView(error: self.viewModel.errorMessage!)
} else if self.viewModel.imageUrls.count == 0 {
VStack {
Text("Loading").foregroundColor(Color("blueDark"))
Text("\(self.viewModel.imageUrls.count)").foregroundColor(Color("blueDark"))
}
} else {
VStack {
UIScrollViewWrapper {
HStack {
ForEach(self.viewModel.imageUrls, id: \.self) { imageUrl in
LoadableImage(url: imageUrl)
.scaledToFill()
}.frame(width: geometry.size.width, height: self.scrollViewHeight)
}.edgesIgnoringSafeArea(.all)
}.frame(width: geometry.size.width, height: self.scrollViewHeight)
Spacer()
}
}
}
}.onAppear(perform: { self.viewModel.fetchDetails() })
.onReceive(viewModel.objectWillChange, perform: {
print("Received new value from view model")
print("\(self.viewModel.imageUrls)")
})
}
}
我的视图模型如下所示:
import Foundation
import Combine
class DetailViewModel : ObservableObject {
@Published var imageUrls: [String] = []
@Published var errorMessage : String?
private var fetcher: Fetchable
private var resourceId : String
init(fetcher: Fetchable, resource: Resource) {
self.resourceId = resource.id
// self.fetchDetails() <-- uncommenting this line results in onReceive being called + a view update
}
// this is a stubbed version of my data fetch that performs the same way as my actual
// data call in regards to ObservableObject updates
// MARK - Data Fetching Stub
func fetchDetails() {
if let path = Bundle.main.path(forResource: "detail", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let parsedData = try JSONDecoder().decode(DetailResponse.self, from: data)
self.imageUrls = parsedData.photos // <-- this doesn't trigger a change, and even manually calling self.objectWillChange.send() here doesn't trigger onReceive/view update
print("setting image urls to \(parsedData.photos)")
} catch {
print("error decoding")
}
}
}
}
如果我在视图模型的 init 方法中获取数据,则在设置 @Published imageUrls 属性时调用视图上的 onReceive 块。但是,当我从 init 方法中删除 fetch 并使用以下方法从视图中调用时:
.onAppear(perform: { self.viewModel.fetchDetails() })
viewModel.objectWillChange 的 onReceive 不会被调用,即使数据已更新。我不知道为什么会这样,并且非常感谢这里的任何帮助。
【问题讨论】:
-
您是如何创建 DetailViewModel 的(即在 SwiftUI 主体块中?)
标签: swiftui combine observableobject