我尝试在SwiftUI中正确地实现MVVM,所以我提出了这个(简化的)模型和ViewModel:
struct Model {
var property1: String
var property2: String
}
class ViewModel: ObservableObject {
@Published var model = Model(property1: "this is", property2: "a test")
}
在View
中使用它可以正常工作,但是我遇到了一些性能问题,因为我用一些计算属性和一些函数扩展了ViewModel
(而且Model
本身更复杂)。但是让我们继续这个例子,因为它完美地展示了我认为SwiftUI本身存在的一个大问题。
想象一下,你有这些视图来显示数据:
struct ParentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
print("redrawing ParentView")
return ChildView(viewModel: self.viewModel)
}
}
struct ChildView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
print("redrawing ChildView")
return VStack {
ViewForTextField(property: self.$viewModel.model.property1)
ViewForTextField(property: self.$viewModel.model.property2)
}
}
}
struct ViewForTextField: View {
@Binding var property: String
var body: some View {
print("redrawing textView of \(self.property)")
return TextField("...", text: self.$property)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
现在,在TextField
中输入文本会导致在我的窗口中重绘 everyView
!打印输出为:
redrawing ParentView
redrawing ChildView
redrawing textView of this is
redrawing textView of a test
redrawing ParentView
redrawing ChildView
redrawing textView of this isa
redrawing textView of a test
redrawing ParentView
redrawing ChildView
redrawing textView of this isab
redrawing textView of a test
...
正如我所看到的,SwiftUI重绘了 every view,因为每个view都在监听ObservedObject
。
我怎么能告诉SwiftUI,它只应该重新绘制那些视图,在那里真正发生了任何变化?
3条答案
按热度按时间vc9ivgsu1#
实际上,MVVM意味着每个视图都有自己的模型,它会在模型更改时更新,而不是所有视图都有一个模型。
因此,不需要在
ParentView
中观察viewModel
,因为它不依赖于它另一种方法是分解视图模型,这样每个视图都有自己的视图子模型,这些子模型将管理自己视图的更新。
w1e3prcc2#
如果所有视图都观察到相同的事物,并且该事物发生了变化,则所有视图都将重新渲染。这是根据定义。没有配置选项来选择性地更新某些视图。
也就是说,您可以通过操纵想要发布的更改来解决它。
例如;
现在,当textfield更改时,
mytext
也会更改,但此更改不会被发布,因此不会触发进一步的视图更新。而且您仍然可以从视图模型访问它。我个人建议使用@State和@EnvironmentObject而不是“视图模型”。它们是处理绑定和查看更新的内置方式,具有大量的安全防护和支持。
此外,你应该尽可能使用值类型而不是引用类型。其他语言的MVVM没有考虑到这一点。
envsm3lx3#
这里有一点需要澄清:当SwiftUI框架加载你的视图时,这并不意味着它们必须被重绘。你的swiftui视图不是绘制代码,它们是SwiftUI框架的说明。
SwiftUI加载你的视图,比较viewids,并有选择地重绘已经更改的内容。有关详细说明,请参阅有关View Identities的WWDC视频。