据我了解,如果需要从视图内部更新视图模型,则需要使其成为绑定变量。
模型。
enum Options: Int, Identifiable, Equatable, CaseIterable {
case option1 = 1
case option2 = 2
case option3 = 3
case option4 = 4
var id: String { "\(self.rawValue)" }
}
class TestViewModel: ObservableObject {
var selectedOption = Options.option1
...
}
视图。
struct TestView: View {
@Binding var viewModel: TestViewModel
@State var selectedOption = Options.option1
var body: some View {
Picker("Option 1", selection: $viewModel.selectedOption) {
ForEach(Options.allCases, id: \.id) { value in
Text(value.id)
.tag(value)
}
}
Text("Selected Option: \(viewModel.selectedOption.rawValue)")
Picker("Option 2", selection: $selectedOption) {
ForEach(Options.allCases, id: \.id) { value in
Text(value.id)
.tag(value)
}
}
Text("Selected Option: \(selectedOption.rawValue)")
}
}
如何使用@Binding更新视图以更新视图?
我想出了可行的解决方案,但对我来说并不好。
...
let b = Binding<Options>(
get: {
viewModel.selectedOption
},
set: {
viewModel.selectedOption = $0
selectedOption = $0 // << this forces the view to refresh
}
)
Picker("Speed 1", selection: b) {
ForEach(Options.allCases, id: \.id) { value in
Text(value.id)
.tag(value)
}
}
...
答案 0 :(得分:2)
ObservableObject
与ObservedObject
包装器配对使用。在这种情况下,视图模型成为视图真相的来源。所以...
class TestViewModel: ObservableObject {
@Published var selectedOption = Options.option1 // << here !!
...
}
struct TestView: View {
@ObservedObject var viewModel: TestViewModel
Picker("Speed 1", selection: $viewModel.selectedOption) {
ForEach(Options.allCases, id: \.id) { value in
Text(value.id)
.tag(value)
}
}
答案 1 :(得分:0)
我不确定您是否有合理的理由在此处使用ObservableObject
,但是可以通过使用struct
和State
变量轻松达到相同的结果:
struct TestViewModel {
var selectedOption = Options.option1
}
struct TestView: View {
@State var viewModel: TestViewModel
var body: some View {
Picker("Option 1", selection: $viewModel.selectedOption) {
ForEach(Options.allCases, id: \.id) { value in
Text(value.id)
.tag(value)
}
}
}
}