SwiftUI中如何在List的ForEach闭包内更新变量?
SwiftUI中“Cannot assign to property: 'self' is immutable”错误解决方案
问题代码
struct NotesView: View { @State var notesArray = [Note]() public var deleteid: String var body: some View { List{ ForEach(notesArray, id: \._id) { notesArray in NavigationLink(destination: AddNotesView(addNotesViewIdentifier: "updateNote", id: notesArray._id, title: notesArray.title, note: notesArray.note, noteDate: notesArray.date)){ HStack { Text(notesArray.title) deleteid = notesArray._id //ERROR - Cannot assign to property: 'self' is immutable } } } } .onDelete(perform: deleteNoteAtIndex) } } func deleteNoteAtIndex(at offsets: IndexSet){ APIFunctions.functions.DeleteNote(id: _id) }
错误原因
NotesView是值类型(struct),默认情况下struct的存储属性不可变;body是计算属性,其闭包内的self处于不可变上下文,因此无法直接修改deleteid这类普通存储属性。此外你的实现逻辑存在冗余——删除操作根本不需要提前存储id。
修正方案
直接在删除方法中通过索引获取要删除元素的id,无需提前维护deleteid变量。修正后的代码如下:
struct NotesView: View { @State var notesArray = [Note]() var body: some View { List{ // 重命名循环参数避免和全局数组混淆 ForEach(notesArray, id: \._id) { note in NavigationLink(destination: AddNotesView(addNotesViewIdentifier: "updateNote", id: note._id, title: note.title, note: note.note, noteDate: note.date)){ HStack { Text(note.title) // 移除多余的赋值操作 } } } } .onDelete(perform: deleteNoteAtIndex) } func deleteNoteAtIndex(at offsets: IndexSet) { // 获取要删除元素的索引 guard let index = offsets.first else { return } let targetNote = notesArray[index] // 调用删除API APIFunctions.functions.DeleteNote(id: targetNote._id) // 同步更新本地数组,刷新UI notesArray.remove(at: index) } }
补充说明
如果确实需要在View的闭包内修改某个属性,需将其声明为可绑定状态:
- 若属性由当前View管理,使用
@State标记,例如@State var deleteid: String = "" - 若属性由父View传递,使用
@Binding标记
但在当前删除场景下,完全不需要额外维护deleteid,通过索引直接获取目标id是更简洁合理的实现方式。
内容的提问来源于stack exchange,提问作者James J Creston
相关产品推荐
相关产品推荐

