SwiftUI:当最后一个元素被删除时索引超出范围



我用LazyVStack做了一个清单,我实现了清单项的删除功能,但由于某种原因,app崩溃了,"索引超出范围";只有当我试图删除最后一个元素

下面是我的代码:
struct ChecklistView: View {
// Properties
// ==========
@ObservedObject var checklist = Checklist()
@ObservedObject var viewModel: ChecklistViewModel
@Binding var checklistItems: [ChecklistItem]
@State var newItemName = ""
@State var newChecklistItemViewIsVisible = false
@State var presentAddNewItem = true
let offlineMode: Bool
var body: some View {
VStack {
LazyVStack {
ForEach(checklistItems) { item in
HStack {
RowView(checklistItem: $checklistItems[item], viewModel: viewModel)
.listRowInsets(.init(top: 0, leading: 8, bottom: 0, trailing: 0))
.padding(.horizontal, 12)
.padding(.top, 12)
.padding(.bottom, 4)
Button {
//Prints the correct index number for the last element in the array, but when I remove the last element, always crashes.
print(index)
if let index = checklistItems.firstIndex(where: {$0.id == checklistItems[item].id}){
checklistItems.remove(at: index)
}
} label: {
Text("X")
}
}
Divider()
.frame(width: 311)
}
}
}
.frame(width: UIScreen.main.bounds.width - 32)
.background(backgroundSecondary)
.cornerRadius(16)
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(borderGray, lineWidth: 1)
)
}
}

ForEach(checklistItems) { item in中的item不是数组的索引对于checklistItems,它是一个ChecklistItem。然而,你使用它作为索引RowView(checklistItem: $checklistItems[item], ...。这是不对的。

尝试使用indices来解决这个问题:

ForEach(checklistItems.indices, id: .self) { ndx in
HStack {
RowView(checklistItem: $checklistItems[ndx], viewModel: viewModel)
.listRowInsets(.init(top: 0, leading: 8, bottom: 0, trailing: 0))
.padding(.horizontal, 12)
.padding(.top, 12)
.padding(.bottom, 4)
Button {
print(ndx)
checklistItems.remove(at: ndx)
} label: {
Text("X")
}
}
Divider().frame(width: 311)
}

你也可以这样写:

ForEach(Array(zip(checklistItems.indices, checklistItems)), id: .0) { ndx, item in

我找到了一个解决方案,我把我的forEach改为:

ForEach(checklistItems.indices, id: .self) { index in
HStack {
RowView(
checklistItem:
Binding(
get: { self.checklistItems[index] },
set: { self.checklistItems[index] = $0 }
),
viewModel: viewModel
)
.padding(.leading, 12)
if checklistEditMode {
Button {
checklistItems.remove(at: index)
} label: {
Image("XCircle")
.resizable()
.frame(width: 18, height: 18)
}
.padding(.trailing, 12)
}
}
.padding(.horizontal, 12)
.padding(.top, 12)
.padding(.bottom, 4)
Divider()
.frame(width: 311)
}

和它现在工作没有崩溃,感谢这个

最新更新