SwiftUI中数组内指定结构体的删除与编辑问题
解决方案:修复删除逻辑与完善编辑保存功能
一、修复ContentView中的删除操作
你之前的删除代码会清空整个数组,是因为bookData.contains(bookDetail)的判断逻辑有问题——对于数组里的每一个元素,这个条件都会返回true(只要数组里存在该元素),所以removeAll会删掉所有内容。
正确的做法是利用Book的唯一标识符(也就是你在NewBook里用的UUID生成的id)来精准匹配要删除的元素。修改上下文菜单的按钮动作如下:
Button(action: { // 通过id匹配,删除指定的书籍 bookData.removeAll { $0.id == bookDetail.id } // 保存修改后的数组到JSON文件 writeJSON(bookData) }) { Label("Delete", systemImage: "trash") }
二、完善EditBook的编辑与保存逻辑
你的EditBook目前有两个问题:一是没有初始化编辑框的默认值为当前书籍的信息,二是点击"Update book"按钮时没有执行更新和保存操作。我们可以通过初始化方法设置默认值,并在按钮动作中找到数组对应的元素进行修改。
修改后的EditBook代码:
struct EditBook: View { @Binding var bookData: [Book] @State private var name: String @State private var author: String @State private var page: String @State private var total: String let book: Book // 添加环境变量用于返回上一页 @Environment(\.presentationMode) var presentationMode // 初始化时将传入书籍的信息赋值给编辑状态变量 init(bookData: Binding<[Book]>, book: Book) { self._bookData = bookData self.book = book self._name = State(initialValue: book.name) self._author = State(initialValue: book.author) self._page = State(initialValue: book.page) self._total = State(initialValue: book.total) } var body: some View { Form{ Section(header: Text("Change the details of the book")){ HStack{ Text("Name:") // 占位符留空,因为我们已经初始化了当前书籍的名称 TextField("", text: $name) } HStack{ Text("Author:") TextField("", text: $author) } HStack{ Text("Page number:") TextField("", text: $page) .keyboardType(.numberPad) } HStack{ Text("Number of pages:") TextField("", text: $total) .keyboardType(.numberPad) } } Section{ HStack{ Spacer() Button(action: { // 通过id找到数组中对应的书籍索引 if let index = bookData.firstIndex(where: { $0.id == book.id }) { // 更新该位置书籍的属性 bookData[index].name = name bookData[index].author = author bookData[index].page = page bookData[index].total = total // 或者直接替换整个元素(如果需要修改image等其他属性时更方便) // bookData[index] = Book(id: book.id, name: name, author: author, page: page, total: total, image: book.image) // 保存修改后的数组到JSON文件 writeJSON(bookData) // 返回上一页 presentationMode.wrappedValue.dismiss() } }) { Text("Update book") } Spacer() } } } .navigationTitle("Edit Book") } }
三、确保Book结构体符合要求
为了让上述逻辑正常工作,你的Book结构体需要满足两个条件:
- 遵循
Identifiable协议(这样ForEach和firstIndex才能通过id正确识别元素) - 可编辑的属性必须用
var声明(而不是let)
示例Book结构体:
struct Book: Identifiable, Codable { let id: UUID var name: String var author: String var page: String var total: String var image: String }
这样修改后,删除指定书籍和编辑保存的功能就都能正常工作了!
内容的提问来源于stack exchange,提问作者Arnav Motwani
相关产品推荐
相关产品推荐

