ios – Flawed merchandise will get deleted from LazyVGrid

My aim is to create a listing like this in SwiftUI
Each time the person faucets add, a brand new row is created after which on swiping to delete, the respective row must be deleted.
So as to do this, I begin with a really fundamental mannequin
struct SnagItem: Codable {
personal(set) var reference: Int = 0
personal(set) var particulars: String = ""
personal(set) var isCompleted: Bool = false
enum CodingKeys: String, CodingKey, CaseIterable {
case reference = "Reference"
case particulars = "Particulars"
case isCompleted = "IsCompleted"
}
}
extension SnagItem: Hashable { }
I exploit this mannequin inside a view mannequin which I want to bind to my SwiftUI view, that is the view mannequin:
class SnagItemViewModel: ObservableObject {
personal let snagItem: SnagItem
@Revealed var particulars: String = ""
@Revealed var isCompleted: Bool = false
init(withSnagItem snagItem: SnagItem) {
self.snagItem = snagItem
particulars = snagItem.particulars
isCompleted = snagItem.isCompleted
}
}
I’ve one other view mannequin that retains observe of all of the snag gadgets (rows) utilizing an array. This additionally handles the including and deletion of things.
class SnagItemsViewModel: ObservableObject {
@Revealed var snagItems: [SnagItemViewModel] = [SnagItemViewModel(withSnagItem: SnagItem())]
func getSnagItem(at index: Int) -> SnagItemViewModel {
snagItems[index]
}
func addSnagItem() {
snagItems.append(SnagItemViewModel(withSnagItem: SnagItem()))
}
func deleteSnagItemRecord(at indexSet: IndexSet) {
guard let index = indexSet.first else { return }
snagItems.take away(at: index)
}
}
@Revealed var snagItems: [SnagItemViewModel] = [SnagItemViewModel(withSnagItem: SnagItem())]
I’ve created a SwiftUI view that acts as a container:
struct SnagItemsView: View {
@StateObject var snagItemsViewModel: SnagItemsViewModel
var physique: some View {
ForEach(0 ..< snagItemsViewModel.snagItems.rely, id: .self) { snagItemIndex in
let snagItemViewModel = snagItemsViewModel.getSnagItem(at: snagItemIndex)
SnagItemRowView(reference: snagItemIndex + 1,
snagItemViewModel: snagItemViewModel)
}
.onDelete(carry out: delete(at:))
}
func delete(at indexSet: IndexSet) {
withAnimation {
snagItemsViewModel.deleteSnagItemRecord(at: indexSet)
}
}
}
Every row then has it is personal view:
struct SnagItemRowView: View {
@State var reference: Int
@StateObject var snagItemViewModel: SnagItemViewModel
let gridItemColumnConfig = [
GridItem(.fixed(Constants.Frame.minGridItemWidth)),
GridItem(.flexible()),
GridItem(.fixed(Constants.Frame.minGridItemWidth))
]
var physique: some View {
LazyVGrid(columns: gridItemColumnConfig, spacing: 8) {
ForEach(0 ..< SnagItem.CodingKeys.allCases.rely, id: .self) { columnIndex in
let snagItemCategory = SnagItem.CodingKeys.allCases[columnIndex]
if snagItemCategory == .reference {
Textual content("(reference)")
} else if snagItemCategory == .particulars {
TextField(snagItemViewModel.localizedText(for: .enterValue),
textual content: $snagItemViewModel.particulars,
axis: .vertical)
} else {
Toggle("", isOn: $snagItemViewModel.isCompleted)
.labelsHidden()
}
}
}
}
}
All the pieces appears to work positive for probably the most half.
It begins off like this:
When the person faucets Add, one other row is added and doing this a number of occasions provides extra rows:
The problems start, when I attempt to delete:
As you possibly can see I am making an attempt to delete row 3, after deletion that is the result’s that row 4 will get deleted as a substitute, atleast from a UI perspective:
I printed out the values from my get perform and plainly the view mannequin truly appears to have the proper objects, the SwiftUI View would not appear to render the proper information nonetheless for some purpose:
I added a breakpoint in my delete perform, to see if the fitting index was being handed and it looks like all the pieces seems to be good right here:
Lastly, when I attempt to add one other row after the deletion course of, the outdated information appears to be added again once more:
And once more, once I examine the view mannequin, the info appears to be proper, however the SwiftUI view reveals one thing else.
What am I doing unsuitable and the way might I repair this ?
Credit: www.ismmailgsm.com