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

SwiftData实现:点击不同结构体的Cell View删除列表项

解决SwiftUI待办应用点击Cell删除列表项的问题

核心问题分析

你当前代码的关键问题有两个:

  1. ContentView 向 NoteCell 传递的是新建的Note对象(Note(title: item.title, desc: item.desc)),而非noteList中的原对象,导致后续无法通过该对象正确删除数据。
  2. 子视图(NoteCell、iOSCheckboxToggleStyle)没有与父视图建立删除逻辑的通信通道,无法触发modelContext的删除操作。

解决方案

步骤1:修正ContentView,传递原Note对象并提供删除回调

修改ContentView,直接传递noteList中的原item给NoteCell,同时新增接收Note对象的删除方法(避免依赖索引,@Query返回的数组可能随数据变化重新排序,索引不可靠):

struct ContentView: View {
  @Environment(\.modelContext) private var context
  @Query(sort: \Note.title) var noteList: [Note]
  @State private var showEditNoteSheet = false // 补充缺失的状态变量

  var body: some View {
    List {                  
      ForEach(noteList, id: \.id) { item in
        NoteCell(myNote: item, onDelete: {
          deleteItem(note: item)
        }, onEdit: {
          showEditNoteSheet = true
        })
        .sheet(isPresented: $showEditNoteSheet, content: {
          EditNoteSheet(noteTitle: item.title, noteDesc: item.desc)
        })
      }
      .onDelete(perform: { indexSet in
        indexSet.forEach { index in
          deleteItem(note: noteList[index])
        }
      })
    }
  }
 
  func deleteItem(note: Note){
    context.delete(note)
    // 可选:立即同步数据
    // try? context.save()
  }
}

步骤2:修改NoteCell,添加删除回调闭包并实现点击删除

在NoteCell中新增onDelete闭包参数,点击Cell或勾选复选框时触发该闭包,由父视图处理删除逻辑:

struct NoteCell: View {
  var myNote: Note
  let onDelete: () -> Void // 删除回调
  let onEdit: () -> Void // 编辑回调
  @State var isChecked = false
  @State var noteSheet = false
    
  var body: some View {
    Button {
      onEdit() // 点击Cell触发编辑弹窗
      // 若需点击Cell直接删除,替换为 onDelete()
    } label: {
      HStack {
        Toggle(isOn: $isChecked) {
        }
        .toggleStyle(iOSCheckboxToggleStyle(onToggle: { isOn in
          if isOn {
            onDelete() // 勾选复选框时触发删除
          }
        }))
                 
        Text(myNote.title)
      }
      .foregroundStyle(.black)
    }
    .sheet(isPresented: $noteSheet, content: {
      AddNoteSheet(noteTitle: myNote.title, noteDesc: myNote.desc)
    })
  }
}

步骤3:修改自定义ToggleStyle,添加勾选回调(可选)

如果需要勾选复选框时触发删除,给iOSCheckboxToggleStyle添加回调闭包传递勾选状态:

struct iOSCheckboxToggleStyle: ToggleStyle {
  let onToggle: (Bool) -> Void // 勾选状态变化回调
  
  func makeBody(configuration: Configuration) -> some View {
    Button(action: {        
      configuration.isOn.toggle()
      onToggle(configuration.isOn) // 将状态传递给父视图
    }, label: {
      HStack {
        Image(systemName: configuration.isOn ? "checkmark.square" : "square")
        configuration.label
      }
    })
  }
}

关键说明

  • 避免依赖数组索引删除:@Query返回的noteList是动态数组,数据变化时索引会重新排序,直接使用Note对象删除更可靠。
  • 子视图通过闭包解耦逻辑:删除操作由持有modelContext的父视图处理,子视图仅负责触发动作,符合SwiftUI单向数据流原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:07:44