0

我有一个用 LazyVStack 制作的清单,我为清单项目实现了删除功能,但由于某种原因,只有当我尝试删除最后一个元素时,应用程序才会因“索引超出范围”而崩溃

这是我的代码:

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)
        )
    }
}
4

2 回答 2

0

The item from your ForEach(checklistItems) { item in is not an index into the array of checklistItems, it is a ChecklistItem. However you are using it as an index in the RowView(checklistItem: $checklistItems[item], .... This is not correct.

Try this approach using indices to fix your issue:

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)
}

You can also use this:

ForEach(Array(zip(checklistItems.indices, checklistItems)), id: \.0) { ndx, item in
于 2021-09-17T13:05:13.063 回答
-1

我找到了解决方案,我将 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)
                }

它现在可以正常工作,没有崩溃,多亏了这个

于 2021-09-17T14:46:31.537 回答