我的代码刚刚遇到一个不幸的问题:
class MyViewModel: ObservableObject {
func load() {
// set up Combine subscriptions, etc.
}
}
struct MyView: View {
@ObservedObject private var viewModel = MyViewModel()
var body: some View {
SomeChildView()
.onAppear { self.viewModel.load() }
}
}
我有很多以这种方式构建的视图。(一些)状态和逻辑被卸载到一个视图模型,该模型在onAppear
.
问题是视图可能会被重新渲染,但onAppear
只执行一次。结果是,只要视图被重新渲染一次或多次,视图模型中的任何状态都不会真正反映在视图中,因为只有第一个实例load()
调用了它的方法。
有几种方法可以解决这个问题,但它们都有缺点:
- 我可以将逻辑
load()
移到中init()
,但这似乎很臭,因为init()
它是用于属性分配等简单的事情,而不是用于设置订阅或其他外部访问。此外,我希望能够覆盖用于测试的视图模型逻辑,并且init()
不能被覆盖。编辑:这里更大的问题是我们只想在视图出现时执行一次加载逻辑,而不是每次视图呈现时。 - 我可以从父级传递视图模型,但是如果重新渲染父级,则可能会遇到同样的问题。
- 我可以初始化视图模型
SceneDelegate
并将其作为@EnvironmentObject
. .
我觉得有一种简单的方法可以实现我只是想念的。跳出框框思考,我使用视图模型的原因是为了分离关注点和便于单元测试。我希望视图只与视图模型提供的接口进行交互,而视图模型可以处理所有杂乱的数据访问。我也不确定是否有另一种方法可以在Publisher
不使用ObservableObject
.