macOS笔记类App实现非滑动式删除笔记功能的技术咨询
macOS笔记类App实现非滑动式删除笔记功能的技术咨询
嘿,我完全理解你不想用系统默认的滑动删除、想要更直观的点击操作来删除笔记的需求,这在macOS上完全可以实现,我给你拆解两种方案的具体实现方式:
方案一:点击列表旁的垃圾桶图标删除单条笔记
首先你的NoteListView里目前用的是不可变的let myNotes,要实现删除得把它改成绑定数组,再结合Core Data的上下文操作(从你的代码看是用了Core Data存储笔记),一步步来调整:
- 调整
NoteListView的属性与逻辑:
struct NoteListView: View { // 将不可变数组改为绑定类型,方便更新列表 @Binding var myNotes: [MyNoteViewModel] // 注入Core Data上下文,用于删除实体 @Environment(\.managedObjectContext) private var viewContext var body: some View { List(myNotes) { myNote in HStack{ NoteCellView(noteModel: myNote) Image(systemName: "trash") .foregroundColor(.red) // 给垃圾桶图标添加点击手势,触发删除方法 .onTapGesture { deleteSingleNote(note: myNote) } } } } // 封装单条笔记的删除逻辑 private func deleteSingleNote(note: MyNoteViewModel) { // 从Core Data上下文删除对应的实体 viewContext.delete(note.myNote) // 保存上下文并更新列表 do { try viewContext.save() // 从绑定数组中移除对应的ViewModel if let index = myNotes.firstIndex(where: { $0.id == note.id }) { myNotes.remove(at: index) } } catch { let nsError = error as NSError fatalError("删除失败:\(nsError), \(nsError.userInfo)") } } }
- 调整
MyNoteViewModel的访问权限:
因为要在NoteListView里访问原始的MyNote实体,需要把原本的private let myNote修改为可内部访问的权限:
struct MyNoteViewModel: Identifiable{ // 去掉private,让外部能拿到原始的Core Data实体 let myNote: MyNote init(myNote: MyNote){ self.myNote = myNote } var id: NSManagedObjectID{ myNote.objectID } var name: String { myNote.name ?? "" } }
方案二:添加工具栏按钮实现选中笔记删除
如果还想支持批量删除,可以给列表加上选中功能,再配合工具栏按钮实现:
struct NoteListView: View { @Binding var myNotes: [MyNoteViewModel] @Environment(\.managedObjectContext) private var viewContext // 记录用户选中的笔记ID集合 @State private var selectedNoteIDs: Set<NSManagedObjectID> = [] var body: some View { List(myNotes, selection: $selectedNoteIDs) { myNote in HStack{ NoteCellView(noteModel: myNote) Image(systemName: "trash") .foregroundColor(.red) .onTapGesture { deleteSingleNote(note: myNote) } } } // 添加工具栏删除按钮 .toolbar { Button(action: deleteSelectedNotes) { Image(systemName: "trash") } // 没有选中笔记时禁用按钮 .disabled(selectedNoteIDs.isEmpty) } } // 单条笔记删除方法(和方案一一致) private func deleteSingleNote(note: MyNoteViewModel) { viewContext.delete(note.myNote) do { try viewContext.save() if let index = myNotes.firstIndex(where: { $0.id == note.id }) { myNotes.remove(at: index) } } catch { let nsError = error as NSError fatalError("删除失败:\(nsError), \(nsError.userInfo)") } } // 批量删除选中笔记的方法 private func deleteSelectedNotes() { // 筛选出所有选中的笔记实体并删除 let selectedNotes = myNotes.filter { selectedNoteIDs.contains($0.id) } selectedNotes.forEach { viewContext.delete($0.myNote) } do { try viewContext.save() // 从绑定数组中移除已删除的笔记 myNotes.removeAll { selectedNoteIDs.contains($0.id) } // 清空选中状态 selectedNoteIDs.removeAll() } catch { let nsError = error as NSError fatalError("批量删除失败:\(nsError), \(nsError.userInfo)") } } }
补充说明
- 如果你的笔记不是存在Core Data里,而是普通的内存数组,那删除逻辑会更简单,只需要从绑定数组里移除对应的元素即可,不用处理上下文保存的步骤。
- 在macOS上,
.onTapGesture的用法和iOS完全一致,你之前的思路是对的,只是缺少了绑定数组和数据持久化层的操作逻辑。
备注:内容来源于stack exchange,提问作者jari85
相关产品推荐
相关产品推荐

