我有一个内容 View ,我在其中使用 ForEach 显示项目列表
@ObservedObject var homeVM : HomeViewModel
var body: some View {
ScrollView (.horizontal, showsIndicators: false) {
HStack(spacing: 10) {
Spacer().frame(width:8)
ForEach(homeVM.favoriteStores , id: \._id){ item in
StoreRowOneView(storeVM: item)
}
Spacer().frame(width:8)
}
}.frame(height: 100)
}
还有我的
ObservableObject
包含@Published var favoriteStores = [StoreViewModel]()
和
StoreViewModel
定义如下class StoreViewModel : ObservableObject {
@Published var store:ItemStore
init(store:ItemStore) {
self.store = store
}
var _id:String {
return store._id!
}
}
如果我直接填充数组,它工作正常,我可以看到商店列表
但是如果我在网络调用(后台作业)之后填充了数组,则 View 不会收到有更改的通知
StoreApi().getFavedStores(userId: userId) { (response) in
guard response != nil else {
self.errorMsg = "Something wrong"
self.error = true
return
}
self.favoriteStores = (response)!.map(StoreViewModel.init)
print("counnt favorite \(self.favoriteStores.count)")
}
但奇怪的是:
- 如果我添加一个显示数组项计数的文本, View 将得到通知并且一切正常
那就是我的意思 :
@ObservedObject var homeVM : HomeViewModel
var body: some View {
ScrollView (.horizontal, showsIndicators: false) {
HStack(spacing: 10) {
Spacer().frame(width:8)
ForEach(homeVM.favoriteStores , id: \._id){ item in
StoreRowOneView(storeVM: item)
}
Text("\(self.homeVM.favoriteStores.count)").frame(width: 100, height: 100)
Spacer().frame(width:8)
}
}.frame(height: 100)
}
对此有何解释?
最佳答案
对于水平 ScrollView,您需要固定高度或只使用条件 ScrollView,它将在 someModels.count > 0
时显示
var body: some View {
ScrollView(.horizontal) {
HStack() {
ForEach(someModels, id: \.someParameter1) { someModel in
someView(someModel)
}
}.frame(height: someFixedHeight)
}
}
// or
var body: some View {
VStack {
if someModels.count > 0 {
ScrollView(.horizontal) {
HStack() {
ForEach(someModels, id: \.someParameter1) { someModel in
someView(someModel)
}
}
}
} else {
EmptyView()
// or other view
}
}
}
通过实现正确地符合 Hashable 协议(protocol)
func hash(into hasher: inout Hasher) {
hasher.combine(someParameter1)
hasher.combine(someParameter2)
}
和
static func == (lhs: SomeModel, rhs: SomeModel) -> Bool {
lhs.someParameter1 == rls.someParameter1 && lhs.someParameter2 == rls.someParameter2
}
并且还遵循@Asperi 建议使用模型中的正确 id,它必须对每个元素都是唯一的。
ForEach(someModels, id: \.someParameter1) { someModel in
someView(someModel)
}
ForEach
没有别的办法通知唯一 ID 以外的更新。Text(someModels.count)
正在工作,因为它会在更改计数时通知更改。
关于ObservedObject 更改时 SwiftUI View 未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59754160/