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

macOS笔记类App实现非滑动式删除笔记功能的技术咨询

macOS笔记类App实现非滑动式删除笔记功能的技术咨询

嘿,我完全理解你不想用系统默认的滑动删除、想要更直观的点击操作来删除笔记的需求,这在macOS上完全可以实现,我给你拆解两种方案的具体实现方式:

方案一:点击列表旁的垃圾桶图标删除单条笔记

首先你的NoteListView里目前用的是不可变的let myNotes,要实现删除得把它改成绑定数组,再结合Core Data的上下文操作(从你的代码看是用了Core Data存储笔记),一步步来调整:

  1. 调整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)")
        }
    }
}
  1. 调整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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 07:18:02