我有一个 MainViewModel,它保存具有关联对象的枚举数组。但是,当我在 SwiftUI 视图中使用它时,变量会丢失其 @Published 包装器,并且 UI 不会更新或收到更改通知。如何保留变量的 @Published 状态?
这是我的代码:
// Enum with associated types
enum ViewType: Hashable, Identifiable {
case .a(ViewModelA)
case .b(ViewModelB)
case .c(ViewModelC)
}
// classes used in associated types
class ViewModelA: ObservableObject {
@Published var listIndex: Int = 1
//some other properties
}
class ViewModelB: ObservableObject {
@Published var name: String = "hello"
//some other properties
}
class ViewModelC: ObservableObject {
@Published var isOn: Bool = false
//some other properties
}
// then I create an array in my mainViewModel
// to use in my SwiftUI view
class MainViewModel: ObservableObject {
@Published var viewTypeArray: [ViewType] = [] // add items to it based on the backend response (assume I have 4 items)
}
// then I use the viewModel in my view
struct MyView: View {
@ObservedObject viewModel: MainViewModel
init(viewModel: MainViewModel) {
self.viewModel = viewModel
}
var body: some View {
ForEach(viewModel.viewTypeArray) { view in
case .a(let viewModelA):
// I display something
// I loose the ObservableObject wrapper
// then I lose the connection to @Published wrapper properties ex: `listIndex`
// and no ui updates will trigger here
case .b(let viewModelB):
// I display something
// I loose the ObservableObject wrapper
// then I lose the connection to @Published properties ex: `name`
// and no ui updates will trigger here
case .c(let viewModelC):
// I display something
// I loose the ObservableObject wrapper
// then I lose the connection to @Published properties ex: `isOn`
// and no ui updates will trigger here
}
}
}
我尝试为每个子 ViewModel(例如 ViewModelA、ViewModelB)使用 ObservableObject 包装器来保持与视图的直接连接,但这不起作用。我想使用具有关联类型的枚举以及 @ObservableObject 和 @Published 包装器,以确保更改正确更新 SwiftUI 视图。
您可以使用包装器有选择地公开特定的
@Published
属性。
struct PropertyWrapper<T: ObservableObject, Content: View>: View {
@ObservedObject private var value: T
private var content: (T) -> Content
init(value: T, @ViewBuilder content: @escaping (T) -> Content) {
self.value = value
self.content = content
}
var body: some View {
content(value)
}
}
然后按如下方式使用它:在
case .b
ForEach(viewModel.viewTypeArray) { view in
switch view {
case .a(let viewModelA):
// I display something
// I loose the ObservableObject wrapper
// then I lose the connection to @Published wrapper properties ex: `listIndex`
// and no ui updates will trigger here
case .b(let viewModelB):
PropertyWrapper(value: viewModelB) { object in
Text(object.name) // this should update the UI properly when `name` updates
}
case .c(let viewModelC):
// I display something
// I loose the ObservableObject wrapper
// then I lose the connection to @Published properties ex: `isOn`
// and no ui updates will trigger here
}
}
我希望这能如预期那样进行。玩得开心。