SwiftUI中创建新文件夹时如何实现每个文件夹对应独立NoteView
解决三栏笔记应用中文件夹与笔记独立关联的问题
核心问题根源
所有文件夹共用同一个NoteView,且Core Data中Note与Folder实体未建立关联,导致笔记全局共享,无法区分归属。
分步解决方案
1. 配置Core Data实体关联
打开Core Data模型文件,给Note实体添加folder属性,类型为Folder,设置关联关系为一对一(每个笔记属于一个文件夹);同时给Folder实体添加notes属性,类型为Note的集合,设置反向关联到Note的folder属性。
2. 修改Sidebar传递选中文件夹
在Sidebar的NavigationLink中,将当前选中的folder作为参数传入NoteView:
List(folders, selection: $selectedFoldersIds){folder in NavigationLink(folder.folderName, destination: NoteView(selectedFolder: folder)) }
3. 重构NoteView实现文件夹专属笔记过滤
修改NoteView,通过传入的文件夹过滤笔记,并在创建笔记时关联到当前文件夹:
struct NoteView: View { let selectedFolder: Folder @Environment(\.managedObjectContext) private var viewContext @State private var isPresented: Bool = false // 根据选中文件夹过滤笔记的FetchRequest @FetchRequest var notes: FetchedResults<Note> init(selectedFolder: Folder) { self.selectedFolder = selectedFolder _notes = FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \Note.name, ascending: true)], predicate: NSPredicate(format: "folder == %@", selectedFolder) ) } @State private var selectedNotesIds: Set<Note.ID> = [] private var selectedNote: Note?{ guard let selectedNoteId = selectedNotesIds.first, let selectedNote = notes.filter ({$0.id == selectedNoteId}).first else{ return nil } return selectedNote } var body: some View { List(notes, selection: $selectedNotesIds){ note in NavigationLink(note.name, destination: NoteEditor(note: note )) } .toolbar{ ToolbarItem(placement: .primaryAction){ Button(action: createNote){ Label("创建笔记", systemImage: "square.and.pencil") } } ToolbarItem(placement: .primaryAction){ Button(action: deleteSelectedNotes){ Label("删除笔记", systemImage: "trash") } } } } // 创建笔记时关联到当前文件夹 private func createNote(){ createNote(name: "新笔记", text: "") } private func createNote(name: String, text: String) { withAnimation { let note = Note(context: viewContext) note.id = UUID() note.name = name note.text = text note.folder = selectedFolder // 绑定到当前文件夹 do { try viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } } private func deleteSelectedNotes(){ withAnimation{ let selectedNotes = notes.filter {selectedNotesIds.contains($0.id)} deleteNotes(notes: selectedNotes) } } private func deleteNotes(notes: [Note]){ viewContext.perform{ notes.forEach(viewContext.delete)} } }
4. 效果验证
现在每个文件夹打开的NoteView只会显示自身关联的笔记,新创建的笔记自动归属到当前选中的文件夹,不同文件夹的笔记完全独立,符合常规笔记应用的逻辑。
内容的提问来源于stack exchange,提问作者jari85
相关产品推荐
相关产品推荐

