【发布时间】:2021-04-28 13:23:55
【问题描述】:
我在下面的视图中有一个包含已完成/未完成部分的任务列表,但是当尝试编辑列表中的一项时,始终选择该部分的最后一项,甚至不允许删除。它在测试该部分内的所有记录都是一条记录时看起来,因此删除幻灯片不起作用,并且在编辑它时会获取最后一条记录。下面是完整的代码,以便您尝试帮助我确定问题所在。
import SwiftUI
import CoreData
import UserNotifications
struct ListView: View {
@Environment(\.presentationMode) var presentationMode
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(fetchRequest: Task.taskList(),animation: .default) private var items: FetchedResults<Task>
@State var isAddFormPresented: Bool = false
@State var taskToEdit: Task?
init(predicate: NSPredicate?, sortDescriptor: NSSortDescriptor) {
let fetchRequest = NSFetchRequest<Task>(entityName: Task.entity().name ?? "Task")
fetchRequest.sortDescriptors = [sortDescriptor]
if let predicate = predicate {
fetchRequest.predicate = predicate
}
_items = FetchRequest(fetchRequest: fetchRequest)
UITableViewCell.appearance().backgroundColor = .white
UITableView.appearance().backgroundColor = .white
}
var body: some View {
let data = groupedEntries(self.items)
VStack(alignment: .center) {
if data.isEmpty {
Spacer()
Image("empty")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 250, height: 250)
.clipShape(Circle())
.overlay(Circle().stroke(Color.pink, lineWidth: 2))
Spacer()
} else {
List {
ForEach(data, id: \.self) { (section: [Task]) in
Section(header: Text(section[0].isComplete == false ? "Incomplete" : "Completed")
.font(.body)
.foregroundColor(section[0].isComplete == false ? Color.pink : Color.green)
){
self.completedView(section: section)
}
.sheet(item: $taskToEdit, onDismiss: {
self.taskToEdit = nil
}) { task in
TaskFormView(
taskToEdit: task,
name: task.name!,
taskDetails: task.taskDetails ?? "",
important: TaskType2(rawValue: task.important ?? "") ?? .none,
urgent: TaskType(rawValue: task.urgent ?? "") ?? .none,
secondaryCategory: Category(rawValue: task.secondaryCategory ?? "") ?? .other,
isComplete: task.isComplete,
dateAdded: task.dateAdded ?? Date()
)
}
}
}
.listStyle(SidebarListStyle())
HStack {
Spacer()
Button(action: addTapped) {
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 30, height: 30)
.shadow(radius: 20)
}
.padding(.trailing, 40)
.padding(.bottom, 24)
.accentColor(Color(UIColor.systemRed))
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(UIColor.systemYellow).opacity(0.5))
.edgesIgnoringSafeArea(.all)
.sheet(isPresented: $isAddFormPresented) {
TaskFormView()
.environment(\.managedObjectContext, PersistenceController.shared.container.viewContext)
}
}
func groupedEntries(_ result : FetchedResults<Task>) -> [[Task]] {
return Dictionary(grouping: result) { (element : Task) in
element.isComplete
}
.values.sorted() { $0[0].dateAdded! < $1[0].dateAdded! }
}
func completedView(section: [Task]) -> some View {
ForEach(section, id: \.id) { task in
Button(action: {
taskToEdit = task
}) {
HStack {
CategoryRowView(category: Category(rawValue: task.secondaryCategory!)!, dateAdded: task.dateAdded!)
VStack(alignment: .leading) {
HStack {
if task.isComplete != false {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.pink)
.padding(.top, 10)
.padding(.leading, 5)
}
Text(task.name!)
.font(.system(size: 20, weight: .regular, design: .default))
.foregroundColor(.primary)
.padding(.top, 10)
.padding(.leading, 5)
}
Spacer()
HStack {
Image(systemName: "tag.fill")
.foregroundColor(.secondary)
Text(task.important == "none" ? "Not Important" : "Important")
.font(.system(size: 12, weight: .regular, design: .default))
.foregroundColor(.secondary)
.padding(.vertical)
Text(task.urgent == "none" ? "Not Urgent" : "Urgent")
.font(.system(size: 12, weight: .regular, design: .default))
.foregroundColor(.secondary)
.padding(.vertical)
}
.padding(.leading, 5)
}
.padding(.trailing, 2)
Spacer()
}
.frame(height: 140)
.background(Color(.systemBackground))
.cornerRadius(10)
.shadow(color: .black, radius: 4, x: 0, y: 0)
.padding(.vertical, 5)
}
}
.onDelete { row in
deleteEntry(row: row, in: section)
}
}
func addTapped() {
isAddFormPresented.toggle()
}
private func onReturnTapped() {
self.presentationMode.wrappedValue.dismiss()
}
func deleteEntry(row: IndexSet, in section: [Task]) {
let task = section[row.first!]
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [task.id!.uuidString])
viewContext.delete(task)
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private let itemFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd MMM"
return formatter
}()
【问题讨论】:
-
谢谢fatihyildizhan :)
-
你能将 onDelete 修饰符中的行和节打印到控制台吗?我感觉修饰符的位置不正确。
-
我不能,因为我什至不能滑动记录来激活onDelete来删除记录。
-
您的代码远不是Minimal Reproducible Example,正文中的分组效率很低,为什么不直接使用
NSFetchedResultsController并让CoreData 完成所有分组/排序工作。此外,您的onDelete似乎在部分而不是行上,因此您将获得有关部分的信息而不是任务/行将其向上移动 -
抱歉无法重现,但我完全分享了我正在处理的代码。我不知道如何在这种情况下使用 NSFetchedResultsController 并且 onDelete 就在构建行的 ForEach 中。
标签: swiftui swiftui-list