Noob here, I'm displaying a list in a table of sorts. When I select one of the items in the list, I want to pass an identifier for that selected item to a sheet so I can display some data related to the item selected. The problem I'm having is that each iteration of the loop changes the value of the identifier I need to pass. So when I click on a specific item in the list, the value being passed is that of the last identifier in the array not the identifier for the item I have selected.
Here is some code that replicates the issue I'm having.
struct Test: View {
@StateObject var vm = ViewModel()
var x = 0
var body: some View {
VStack {
ForEach (vm.someData, id: \.self) { row in
Button {
vm.showSheet.toggle()
} label: {
Text("(\(row))")
}
.onChange(of: vm.showSheet) { _ in
if vm.showSheet {
vm.theIdentifer = row
}
}
.sheet(isPresented: $vm.showSheet) {
TheSheet(vm: vm)
}
}
}
.padding()
}
}
extension Test {
@MainActor class ViewModel: ObservableObject {
@Published var showSheet = false
@Published var theIdentifer = 0
@Published var someData = [ 2, 4, 6, 8, 10, 12 ]
}
}
struct TheSheet: View {
@ObservedObject var vm: Test.ViewModel
var body: some View {
VStack {
Text("(\(vm.theIdentifer))")
Button {
vm.showSheet.toggle()
} label: {
Text("Close")
}
}
.frame(width: 400, height: 200)
}
}
What's the solution here? Thanks in advance
Working solution:
Observations:
.sheet(isPresented: $vm.showSheet) { TheSheet(vm: VM) }outside of yourForEachloop.showSheetto true in your code, the top row (which is 2) content was displayed first because there was no condition to prevent this.