Я наконец нашел обходной путь: сохраните ViewModel в ContentView, а не в FormView, и передайте его в FormView.
struct ContentView: View {
@State private var showForm = false
@Environment(\.presentationMode) private var presentationMode
private let viewModel = ViewModel()
var body: some View {
NavigationView {
Text("Hello")
.navigationBarItems(trailing: trailingNavigationBarItem)
}
.sheet(isPresented: $showForm) {
FormView(viewModel: self.viewModel)
}
}
private var trailingNavigationBarItem: some View {
Button("Form") {
self.showForm = true
}
}
}
struct FormView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
NavigationView {
Form {
Section(header: Text(viewModel.text)) {
TextView(text: $viewModel.text)
.frame(height: 200)
}
Section(header: Text(viewModel.text)) {
TextField("Text", text: $viewModel.text)
}
}
}
}
}
class ViewModel: ObservableObject {
@Published var text = ""
init() {
print("HERE")
}
}
Единственное, что ViewModel теперь создается правильно, когда ContentView открывается, даже если вы никогда не открываете FormView. Чувствует себя немного расточительно. Особенно, когда у вас есть большой список, с навигационными ссылками на кучу страниц с подробностями, которые теперь все создают свою ViewModel FormView, представленную в виде листа, заранее, даже если вы никогда не покидаете страницу списка.
К сожалению Я не могу превратить ViewModel в структуру, так как на самом деле мне нужно (асинхронно) изменять состояние, а затем в конечном итоге я сталкиваюсь с ошибкой Escaping closure captures mutating 'self' parameter
компилятора. Вздох. Так что да, я застрял с использованием класса.
Проблема root по-прежнему заключается в том, что FormView создается дважды (из-за @Environment(\.presentationMode)
), что также приводит к созданию двух ViewModel (что мой обходной путь решается путем передачи одной копии в оба FormViews в основном). Но все же странно, что это сломалось @Binding
, так как стандартные TextFields работали, как и ожидалось.
В SwiftUI все еще есть много странных ошибок, подобных этой, я очень надеюсь, что этим скоро станет проще управлять. Если кто-нибудь может объяснить поведение листов, ObservableObject
классов (viewmodels), @Environment(\.presentationMode)
и @Binding
вместе взятых, я все уши.