提问人:Justin Comstock 提问时间:12/18/2021 最后编辑:Justin Comstock 更新时间:3/3/2023 访问量:1839
从 SwiftUI 列表中删除包含分区的 CoreData
Deleting CoreData from SwiftUI List with Sections
问:
目标
我想从列表中删除一个项目。我找到的唯一解决方案是对于常规,我已经设法从 UIList 中删除了它,但没有从 CoreData 的 .SectionedFetchRequest
ForEach
FetchRequest
ViewContext
我的问题是独一无二的,因为我正在尝试从与 FetchRequest 不同的 SectionedFetchRequest 中删除
@SectionedFetchRequest(entity: Todo.entity(), sectionIdentifier: \.dueDateRelative, sortDescriptors: [NSSortDescriptor(keyPath: \Todo.dueDate, ascending: true)], predicate: nil, animation: Animation.linear)
var sections: SectionedFetchResults<String, Todo>
var body: some View {
NavigationView {
List {
ForEach(sections) { section in
Section(header: Text(section.id.description)) {
ForEach(section) { todo in
TodoRowView(todo: todo)
.frame(maxWidth: .infinity)
.listRowSeparator(.hidden)
}
.onDelete { row in
deleteTodo(section: section.id.description, row: row)
}
}
}
}
func deleteTodo(section: String, row: IndexSet) {
// Need to delete from list and CoreData viewContex.
}
// My old way of deleting notes with a regular fetch Request
func deleteNote(at offsets: IndexSet) {
for index in offsets {
let todo = todos[index]
viewContext.delete(todo)
}
try? viewContext.save()
}
答:
17赞
lorem ipsum
12/18/2021
#1
这是您使用链接的方式...
将此添加到TodoRowView(todo: todo)
.swipeActions(content: {
Button(role: .destructive, action: {
deleteTodo(todo: todo)
}, label: {
Image(systemName: "trash")
})
})
你需要这个方法在View
public func deleteTodo(todo: Todo){
viewContext.delete(todo)
do{
try viewContext.save()
} catch{
print(error)
}
}
或者,您可以使用当前设置,该设置在onDelete
ForEach
.onDelete { indexSet in
deleteTodo(section: Array(section), offsets: indexSet)
}
使用此方法
func deleteTodo(section: [Todo], offsets: IndexSet) {
for index in offsets {
let todo = section[index]
viewContext.delete(todo)
}
try? viewContext.save()
}
当然,要使这些工作起作用,您需要一个工作
@Environment(\.managedObjectContext) var viewContext
在文件顶部
评论
1赞
Justin Comstock
12/18/2021
成功了!再次感谢。整个数组和 IndexSet 部分仍然令人困惑,我想我需要弄清楚更多。
1赞
lorem ipsum
12/18/2021
@JustinComstock 提供用户已选择删除的索引项 () 集。滑动时,它只有一个,但如果你把一个编辑按钮放在上面,你可以删除多个项目(这就是为什么你需要循环)。每个都有自己的 /array 项目,因此需要传递数组以删除它,因为您必须搜索特定部分。onDelete
indexSet
List
section
ForEach
todo
0赞
abegehr
3/17/2023
在删除节中的最后一项时,我收到“NSInternalInconsistencyException”,原因:“尝试从更新前仅包含 1 项的第 0 节中删除第 1 项”,使用 swipeActions 解决方案。不知道是什么原因。🤔
1赞
lorem ipsum
3/19/2023
@abegehr不知道,我知道这在早期版本的 SwiftUI 和旧版本的 Xcode 中很常见。如果没有最小可重现示例,就不可能帮助您进行故障排除。您可以将其包含在某人会帮助您的问题中。
1赞
malhal
2/6/2023
#2
我在寻找一个简洁的解决方案时发现了这个问题,找不到一个,所以我想我会分享我从中删除的尝试。@SectionedFetchRequest
var body: some View {
NavigationView {
List {
ForEach(sections) { section in
Section(section.id) {
ForEach(section) { todo in
TodoRowView(todo: todo)
.frame(maxWidth: .infinity)
.listRowSeparator(.hidden)
.onDelete { indexSet in
deleteTodos(section: section, offsets: indexSet)
}
}
}
}
}
...
private func deleteTodos(section: SectionedFetchResults<String, Todo>.Section, offsets: IndexSet) {
withAnimation {
offsets.map { section[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
评论
0赞
FrugalResolution
3/3/2023
非常整洁!我喜欢它与原来的相似。
评论
swipeActions