ios - SwiftUI MVVM:父视图更新时重新初始化子视图模型
问题描述
我正在尝试在 SwiftUI 应用程序中使用 MVVM,但是似乎NavigationLink
每当父子视图都被更新时,子视图的视图模型(例如 a 中的视图模型)都会重新初始化ObservableObject
。这会导致孩子的本地状态被重置,网络数据被重新加载等。
我猜这是因为这会导致body
重新评估父级,其中包含SubView
视图模型的构造函数,但我无法找到一个替代方案,让我创建不会超出生命周期的视图模型看法。我需要能够将数据从父视图模型传递给子视图模型。
这是我们试图完成的一个非常简化的操场,其中递增EnvCounter.counter
resets SubView.counter
。
import SwiftUI
import PlaygroundSupport
class EnvCounter: ObservableObject {
@Published var counter = 0
}
struct ContentView: View {
@ObservedObject var envCounter = EnvCounter()
var body: some View {
VStack {
Text("Parent view")
Button(action: { self.envCounter.counter += 1 }) {
Text("EnvCounter is at \(self.envCounter.counter)")
}
.padding(.bottom, 40)
SubView(viewModel: .init())
}
.environmentObject(envCounter)
}
}
struct SubView: View {
class ViewModel: ObservableObject {
@Published var counter = 0
}
@EnvironmentObject var envCounter: EnvCounter
@ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
Text("Sub view")
Button(action: { self.viewModel.counter += 1 }) {
Text("SubView counter is at \(self.viewModel.counter)")
}
Button(action: { self.envCounter.counter += 1 }) {
Text("EnvCounter is at \(self.envCounter.counter)")
}
}
}
}
PlaygroundPage.current.setLiveView(ContentView())
解决方案
Xcode 12 中的 SwiftUI 中添加了一个新的属性包装器,@StateObject
. 您应该能够通过简单地更改@ObservedObject
for来修复它,@StateObject
如下所示。
struct SubView: View {
class ViewModel: ObservableObject {
@Published var counter = 0
}
@EnvironmentObject var envCounter: EnvCounter
@StateObject var viewModel: ViewModel // change on this line
var body: some View {
// ...
}
}
推荐阅读
- java - 如何监听多个 GlobalLayout 事件
- javascript - 等待不等待子函数在反应中首先执行
- javascript - html/js 中的比较表
- node.js - 如何使用 node-postgres 调用使用 refcursor 的 postgresql 函数?
- java - 我可以使用一个参数来指定我想从我的哪个子类中打开我的父类的一个实例吗?
- python - 欧拉方法的数值稳定性
- java - Android Build 显示 No error message Error on using @Query method in DAO
- python - 如何在带有列值的熊猫数据框中使用 if else 和 for 循环
- python - 将命令插入 python ''' 字符串
- python - 在python中编写一个更清洁的函数,一个参数可以是一个集合或一个值