【发布时间】:2020-09-10 23:52:36
【问题描述】:
我试图了解 SwiftUI 中的 MVVM 模式,但我不完全了解 ViewModel 如何侦听和传播来自 Model 对象的更改。许多示例,包括来自 Apple 的 this one,都谈到了让模型继承自 ObservableObject 并直接在您的视图中使用它。这是有道理的。
但是,ViewModel 应该观察其底层模型变化的最佳/推荐方式是什么?
一个简单的例子是WidgetView,它显示了一个小部件的title,但是title可以在后台网络调用中在后台发生变化。
class WidgetView: View {
@ObservedObject var widgetVM = WidgetViewModel()
var body: some View {
Text(widgetVM.title)
}
}
class WidgetViewModel : ObservableObject {
var widget: Widget
var title: String {
get {
// Some translation to the title for this particular view
return widget.title + "!"
}
}
}
struct Widget {
// Some other timer or background process is changing the title
var title: String
}
我探索过的一个粗略的解决方案是拥有一个单独的title 并监听变化。因此,如果Widget 扩展了ObservableObject 和@Published title 字段,那么WidgetViewModel 可以执行以下操作:
class WidgetViewModel : ObservableObject {
var widget: Widget
@Published var title: String = ""
var cancellable: AnyCancellable?
init() {
self.cancellable = widget.$title.receive(on: DispatchQueue.main)
.sink(receiveValue: self.updateTitle )
}
func updateTitle(_: String) {
self.title = widget.title + "!"
}
}
Widget 是否也推荐/标准扩展 ObservableObject?如果是这样,WidgetViewModel 如何正确传递更改通知?看起来WidgetModelView.widget 需要同时是@Published 和@ObservedObject,但这似乎不对。
有人对此有任何见解吗?
【问题讨论】:
-
你不需要
widget是@Published。您的Widget可以通过组合发布对title的更改,如您所展示的,或者您可以使用Notification或您喜欢的任何其他方法。您不需要Widget符合ObservableObject即可拥有title的发布者。您可以为title公开Subject -
假设我使用了从模型到视图模型的不同通知机制(我将研究这些),有没有办法在没有我设置的 Published 属性的情况下通知视图(即我不'不需要在 ViewModel 中有一个单独的标题字段)?
-
不,这是同时拥有模型和视图模型的成本。你的视图模型通常有一堆胶水代码来向上/向下传播事件。