为什么 SwiftUI 中 View 不持有带有 @Observable 的 ViewModel?

问题描述 投票:0回答:1

我正在尝试使用@Observable,但我注意到View并没有使用@State来保持ViewModel。每当 ContentView 中发生变化时,就像 TextField 中的字母一样,ViewModel 就会调用 init。 为什么会发生这种情况,而不是以 ObservableObject 的旧方式发生? 如果有人可以向我解释这是如何工作的以及我如何做得更好,我将非常感激。

示例:

struct ContentView: View {
    @State var text = ""
    var body: some View {
        TextField("Enter text", text: $text)
        SubView()
    }
}

@Observable class SubViewModel {
    var text: String = "Hello, World!"
    init() {
    // -> reload
        print("init SubViewModel")
    }
}

struct SubView: View {
    @State private var viewModel: SubViewModel
    
    init() {
        _viewModel = State(wrappedValue: SubViewModel())
    }
    
    var body: some View {
        Text(viewModel.text)
    }
}

老方法

class SubViewModel: ObservableObject {
    @Published var text: String = "Hello, World!"
    init() {
    // -> doesn't reload
        print("init SubViewModel")
    }
}

struct SubView: View {
    @StateObject private var viewModel: SubViewModel
    
    init() {
        _viewModel = StateObject(wrappedValue: SubViewModel())
    }
    
    var body: some View {
        Text(viewModel.text)
    }
}
ios swift macos swiftui mvvm
1个回答
0
投票

根据文档管理数据,使用

@Observable class
,在视图中形成对可观察数据模型对象的依赖,并且 “当跟踪的属性发生变化时,SwiftUI 会更新视图。如果其他属性发生变化而主体不读取,则视图不受影响并避免不必要的更新。”

避免当

SubView
中只有
text
时重新初始化
TextField
已更改,请尝试此方法,将
SubViewModel
声明移至
ContentView
并将其传递给
SubView
.

 struct ContentView: View {
    @State private var text = ""
    @State private var viewModel = SubViewModel()  // <-- here, source of data truth
    
    var body: some View {
        TextField("Enter text", text: $text)
        SubView(viewModel: viewModel) // <-- here
    }
}

@Observable class SubViewModel {
    var text: String = "Hello, World!"
    
    init() {
        print("---> init SubViewModel")
    }
}

struct SubView: View {
    let viewModel: SubViewModel // <-- here

    var body: some View {
        Text(viewModel.text)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.