SwiftUI:删除最后一个元素时索引超出范围
SwiftUI: Index out of range when last element gets removed
我有一个用 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: {[=10=].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] = [=10=] }
),
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)
}
它现在可以正常工作,没有崩溃,感谢
我有一个用 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: {[=10=].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] = [=10=] }
),
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)
}
它现在可以正常工作,没有崩溃,感谢