我有一个关于SwiftUI和MVVM组合的问题。
在我们开始之前,我已经阅读了一些讨论SwiftUI和MVVM的结合是否必要的帖子。但是我不想在这里讨论这个,因为它已经在其他地方讨论过了。我只想知道它是否可能,如果可能,如何进行。:)
下面是代码。我尝试在更新的Object类之间添加ViewModel层,该类包含一个当按钮被按下时应该更新的数字。问题是,一旦我将ViewModel层放在它们之间,当按钮被按下时,UI不会自动更新。
检视:
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
@ObservedObject var numberStorage = NumberStorage()
var body: some View {
VStack {
// Text("\(viewModel.getNumberObject().number)")
// .padding()
// Button("IncreaseNumber") {
// viewModel.increaseNumber()
// }
Text("\(numberStorage.getNumberObject().number)")
.padding()
Button("IncreaseNumber") {
numberStorage.increaseNumber()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
视图模型:
class ViewModel: ObservableObject {
@Published var number: NumberStorage
init() {
self.number = NumberStorage()
}
func increaseNumber() {
self.number.increaseNumber()
}
func getNumberObject() -> NumberObject {
self.number.getNumberObject()
}
}
型号:
class NumberStorage:ObservableObject {
@Published var numberObject: NumberObject
init() {
numberObject = NumberObject()
}
public func getNumberObject() -> NumberObject {
return self.numberObject
}
public func increaseNumber() {
self.numberObject.number+=1
}
}
struct NumberObject: Identifiable {
let id = UUID()
var number = 0
} ```
Looking forward to your feedback!
3条答案
按热度按时间axr492tv1#
我认为你的代码破坏了MVVM,因为你向视图公开了一个存储模型。在MVVM中,你的ViewModel应该只包含两个东西:
1.您的视图应显示的值。这些值应使用绑定系统(在您的情况下为合并)自动更新。
1.视图可能产生的事件(在你的例子中,一个按钮点击)记住这一点,你的ViewModel应该Package,适配和封装你的模型。我们不希望模型的改变影响视图。这是一个干净的方法:查看方式:
视图模型:
产品型号:
11dmarpk2#
这是一个简单的问题。SwiftUI还不支持嵌套的可观察对象。我认为这里不需要ViewModel+Model,因为ViewModel似乎就足够了。
要实现这一点,您必须在触发模型的
objectWillChange
时手动触发viewModel的objectWillChange
:加:
由于不是注入,而是在视图中初始化viewModel,所以最好使用
StateObject
而不是ObservedObject
。请参阅Apple文档中的参考:Managing model data in your app57hvy0tb3#
处理这个问题的一种方法是观察
Storage
类中的发布者,并在objectWillChange
发布者发生变化时发送它。我在个人项目中通过添加一个类来实现这一点,我的所有视图模型都从这个类继承,它提供了一个很好的接口,并像这样处理合并的东西:父视图模型
特定视图模型
检视
型号/存储
这会导致每次
Storage.numberObject
更改时视图都会重新呈现。