I've implemented a two-way binding in a Foreach statement that seems to work properly:
struct ContentView: View {
@ObservedObject var dataManager: ContentViewModel
var body: some View {
ScrollView(.horizontal, showsIndicators: false){
HStack(spacing: 20){
ForEach($dataManager.data) { $item in
if item.status == true {
Button(item.tag){
item.status.toggle()
}
.foregroundColor(.white)
.background(Color.red)
} else {
Button(item.tag){
item.status.toggle()
}
.foregroundColor(.white)
.background(Color.blue)
}
}
}
}
}
}
The problem is when I've to use some nested views like:
struct ContentView: View {
@ObservedObject var dataManager: ContentViewModel
var body: some View {
ScrollView(.horizontal, showsIndicators: false){
HStack(spacing: 20){
ForEach($dataManager.data) { $item in
if item.status == true {
DetailView(dataManager: dataManager, item: item)
.foregroundColor(.white)
.background(Color.red)
} else {
Button(item.tag){
item.status.toggle()
}
.foregroundColor(.white)
.background(Color.blue)
}
}
}
}
}
}
and:
struct DetailView: View {
@ObservedObject var dataManager: ContentViewModel
var item: SMTTagBoardItem
var body: some View {
Button(item.tag){
item.status.toggle()
}
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
DetailView(dataManager: ContentViewModel(), item: SMTTagBoardItem(id: UUID(), tag: "tag1", rank: 0, status: true))
}
}
I receive this error:
Cannot use mutating member on immutable value: 'self' is immutable
at line :
item.status.toggle()
How can I implement a two-way binding in a ForEach statement that works by passing values to nested views?
CodePudding user response:
First of all, instead of using @ObservedObject, use EnvironmentObject and StateObject.
Then instead of var item
use @Binding var item
. (I think dataManager.data is @Published variable)
ContentView
struct ContentView: View {
@StateObject var dataManager: ContentViewModel
var body: some View {
ScrollView(.horizontal, showsIndicators: false){
HStack(spacing: 20){
ForEach($dataManager.data) { $item in
if item.status == true {
DetailView(item: $item)
.environmentObject(dataManager)
.foregroundColor(.white)
.background(Color.red)
} else {
//more code
}
}
}
}
}
}
DetailView
struct DetailView: View {
@EnvironmentObject var dataManager: ContentViewModel
@Binding var item: SMTTagBoardItem
var body: some View {
Button(item.tag){
item.status.toggle()
}
}
}