Realm/SwiftUI删除笔记时触发Index 2越界崩溃问题求助
解决Realm List删除笔记时索引越界崩溃问题
问题描述
添加3条笔记后,删除第一条或第二条笔记时应用崩溃,抛出错误:Index 2 is out of bounds (must be less than 2)
崩溃原因
问题出在通过固定索引访问实时更新的Realm集合上:@ObservedResults是与Realm数据库实时同步的动态集合,当你删除元素后,集合会立即刷新,但onDelete传递的索引基于删除前的List状态,此时用该索引去访问已经更新后的notes集合,就会出现索引越界。
解决方案
1. 改用Realm原生集合删除方法
修改ViewModel的删除逻辑,直接接收IndexSet并利用@ObservedResults提供的remove(atOffsets:)方法,该方法会自动处理Realm写入和集合同步,完全避免索引不一致问题:
class NoteViewModel: ObservableObject { @ObservedResults(Note.self) var notes @Published var newNoteText: String = "" // 其他方法保持不变... // 替换原deleteNote方法 func deleteNotes(at offsets: IndexSet) { $notes.remove(atOffsets: offsets) } }
2. 简化视图中的删除调用
将List的onDelete闭包直接指向新的删除方法:
List { ForEach(viewModel.notes) { note in // 原HStack内容保持不变... } .onDelete(perform: viewModel.deleteNotes) // 直接传递方法引用 .listRowSeparator(.hidden) }
3. 额外优化:移除冗余Realm实例创建
原代码中手动创建Realm实例的方式可以简化,利用@ObservedResults和Realm对象的内置关联:
- 优化
addNote方法:
func addNote() { guard !newNoteText.isEmpty else { return } let note = Note() note.id = getNextNoteId() note.title = newNoteText note.isCompleted = false $notes.append(note) // 直接通过关联的集合添加 newNoteText = "" }
- 优化
markNoteAsCompleted方法:
func markNoteAsCompleted(id: Int) { guard let note = notes.first(where: { $0.id == id }) else { return } try! note.realm?.write { note.isCompleted.toggle() } }
为什么原代码会崩溃
当你触发删除操作时,Realm会立即更新@ObservedResults集合。原代码中先通过notes[index]获取ID,再去数据库中查找删除,但在这个过程中,集合可能已经因为Realm的实时同步发生了变化,导致后续操作使用的索引与当前集合状态不匹配,最终触发索引越界错误。
内容的提问来源于stack exchange,提问作者Max Elmers
相关产品推荐
相关产品推荐

