ali*_*ego 2 xcode ios swift swiftui
我是 MVVM 世界的新手,想知道在呈现新视图时设置该视图的 ViewModel 属性的最佳方法是什么?
我尝试在呈现视图的 .fullScreenCover 中初始化 ViewModel 类,但这给我带来了各种各样的问题。这就是我所做的:
struct FirstView: View {
@State var isActive = false
var body: some View {
Text("Tap here to go to SecondView")
.onTapGesture {
isActive = true
}
.fullScreenCover(isPresented: $isActive, content: {
SecondView(viewModel: ViewModel(), isActive: $isActive)
})
}
}
struct SecondView: View {
@ObservedObject var viewModel: ViewModel
@Binding var isActive: Bool
init(viewModel: ViewModel, isActive: Binding<Bool>) {
self.viewModel = viewModel
self._isActive = isActive
}
var body: some View {
Button(action: {
$isActive = false
}, label: {
Text("Go back to FirstView")
})
}
}
Run Code Online (Sandbox Code Playgroud)
问题是 viewModel 的 init 方法被调用了很多次。我不确定这是否是因为底层 FirstView 正在被重绘,尽管不再显示在屏幕上,或者是否与 SecondView 中访问的绑定 isActive var 有关。无论如何,都会创建如此多的 viewModel。我不知道这是为什么。但更重要的是我想知道初始化新视图的 viewModel 的正确方法是什么。
我目前正在做的是在 FirstView 的 viewModel 中创建 SecondView 的 viewModel 并传递引用,但这感觉非常错误。
一般来说,您应该@StateObject在初始化ViewModel. 如果您只需要在 中SecondView,那么您不需要将它从 传递FirstView到SecondView,您可以在 中初始化它SecondView:
struct SecondView: View {
@StateObject var viewModel: ViewModel = ViewModel()
Run Code Online (Sandbox Code Playgroud)
但是,如果您需要在第一个视图中引用它,或者您希望无论创建 SecondView 如何保留它,那么您可以FirstView使用以下方法在父视图(在本例中)中初始化它:
@StateObject var viewModel = ViewModel()
Run Code Online (Sandbox Code Playgroud)
然后将该对象传递给子视图 ( SecondView):
SecondView(viewModel: viewModel...
Run Code Online (Sandbox Code Playgroud)
正如您已经拥有的那样,它应该位于@ObservedObject子视图中:
@ObservedObject var viewModel: ViewModel
Run Code Online (Sandbox Code Playgroud)
或者,您可以将其初始化为 an@EnvironmentObject并将其传递到环境中,而不是通过初始化器直接将其从视图传递到视图。
我发现很多人都遇到了这个问题,所以如果你想更好地理解,我制作了一些 YouTube 教程:
如何使用@StateObject和@ObservableObject
| 归档时间: |
|
| 查看次数: |
2212 次 |
| 最近记录: |