You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI 删除列表最后一个元素时出现Index out of range崩溃

问题根因

  1. 你错误地将遍历得到的ChecklistItem实例作为数组下标使用,访问checklistItems[item]属于非法操作。数组下标只能为Int类型,你这种写法本身就存在逻辑漏洞,当删除最后一个元素时数组长度缩减,失效的下标访问直接触发越界崩溃。
  2. 删除逻辑冗余,你已经持有当前遍历到的item实例,完全不需要再通过数组下标访问获取id,直接使用item.id即可。

修复方案

1. 修改ForEach遍历方式

直接遍历绑定数组,拿到单个元素的绑定,避免手动处理下标:

// 原来的写法
ForEach(checklistItems) { item in
// 修改为
ForEach($checklistItems) { $item in

2. 修正RowView的绑定传参

不需要再通过数组下标取绑定,直接传入遍历得到的$item:

// 原来的写法
RowView(checklistItem: $checklistItems[item], viewModel: viewModel)
// 修改为
RowView(checklistItem: $item, viewModel: viewModel)

3. 简化删除逻辑

直接用当前item的id查找索引,避免非法下标访问:

Button {
    if let index = checklistItems.firstIndex(where: { $0.id == item.id }) {
        checklistItems.remove(at: index)
    }
} label: {
    Text("X")
}

修复后完整代码

struct ChecklistView: View {
    // 属性
    // ==========
    @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: $item, viewModel: viewModel)
                            .listRowInsets(.init(top: 0, leading: 8, bottom: 0, trailing: 0))
                            .padding(.horizontal, 12)
                            .padding(.top, 12)
                            .padding(.bottom, 4)

                        Button {
                            if let index = checklistItems.firstIndex(where: {$0.id == 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)
        )
    }
}

内容的提问来源于stack exchange,提问作者Hussein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 02:30:01