can't use @Environment for Binding?

@Environment can't use for Binding?

@Observable
final class View1Model {
var text: String = ""
}
struct View1: View {
@State var viewModel = View1Model()
var body: some View {
View2()
.environment(viewModel)
}
}
struct View2: View {
@Environment(View1Model.self) var viewModel
var body: some View {
TextField("Text", text: $viewModel.text) // Cannot find '$viewModel' in scope
}
}
Answered by zunda in 762819022
struct TitleEditView: View {
@Environment(Book.self) private var book
var body: some View {
@Bindable var book = book
TextField("Title", text: $book.title)
}
}

I found this from Bindable Document https://developer.apple.com/documentation/swiftui/bindable

thanks @macrojd

Why don't you declare an environmentObject ?

 @EnvironmentObject var viewModel: View1Model

I also had that problem, this is the solution: add @Bindable var viewModel = viewModel in your view’s body, even though I don’t think it is elegant.

@Observable
final class View1Model {
var text: String = ""
}
struct View1: View {
@State var viewModel = View1Model()
var body: some View {
View2()
.environment(viewModel)
}
}
struct View2: View {
@Environment(View1Model.self) var viewModel
var body: some View {
// use @Bindable to get the binding
@Bindable var viewModel = viewModel
TextField("Text", text: $viewModel.text)
}
}

This code has good performance. But it is not cleaner than @EnvironmentObject

struct View2: View {
@Environment(View1Model.self) var viewModel
var body: some View {
TextField("Text", text: Binding(get: {
viewModel.text
}, set: { newValue in
viewModel.text = newValue
}))
}
}

The most elegant solution I've found is to extract the view and pass the model to a @Bindable property.

@Observable
final class View1Model {
var text: String = ""
}
struct View1: View {
@State var viewModel = View1Model()
var body: some View {
View2()
.environment(viewModel)
}
}
struct View2: View {
@Environment(View1Model.self) var viewModel
var body: some View {
View3(viewModel: viewModel)
}
}
struct View3: View {
@Bindable var viewModel: ViewModel
var body: some View {
TextField("Text", text: $viewModel.text)
}
}

You can also create an inline bindable:

TextField("Text", text: Bindable(viewModel).text)
Accepted Answer
struct TitleEditView: View {
@Environment(Book.self) private var book
var body: some View {
@Bindable var book = book
TextField("Title", text: $book.title)
}
}

I found this from Bindable Document https://developer.apple.com/documentation/swiftui/bindable

thanks @macrojd

can't use @Environment for Binding?
 
 
Q