How can I refresh a FetchRequest when I select a different date on a DatePicker? meaning I have a view with a datepicker, onchange of dateselected I want to see ONLY items completed on that date. My code is below but I keep getting an error that I cannot mutate a Fetchrequest.
Thanks in advance for your feedback how to solve this dynamic core data fetch request? (dynamically fetch when changing date picker).
thanks!
struct DoneView: View {
@Environment(\.managedObjectContext) var viewContext
//@EnvironmentObject var model: ContentModel
@FetchRequest var fetchRequest: FetchedResults<ToDoItem>
@State var dateSelected : Date = Date() //receive from prev view
@State var selectedDateSub: Date
@State var isPresented: Bool = false
@State var taskDesc : String = ""
@State var taskDetail : String = ""
@State var taskUUID : UUID = UUID()
init() {
let calendar = Calendar.current
let startDate = calendar.startOfDay(for: dateSelected)
let endDate = calendar.date(byAdding: .day, value: 1, to: startDate)!
let predicate = NSPredicate(format: "date_completion >= %@ AND date_completion < %@", argumentArray: [startDate, endDate])
_fetchRequest = FetchRequest<ToDoItem>(sortDescriptors: [NSSortDescriptor(keyPath: \ToDoItem.timestamp, ascending: false)], predicate: predicate)
}
var body: some View {
VStack{
Text("Done Today").font(.title)
//select day
DatePicker("Select date", selection: $dateSelected, displayedComponents: .date)
.datePickerStyle(GraphicalDatePickerStyle())
.frame(maxHeight: 400)
.onChange(of: dateSelected) { val in
}
List {
ForEach(getDoneItemsForThatDate(dateSelected: dateSelected), id: \.self) { task in
Button {
//Text(task.desc!)
} label: {
//Rectangle().foregroundColor(task.done ? .green : .white).frame(height: 40).cornerRadius(10)
Text(task.desc!)
.foregroundColor(task.done ? .white : task.today ? .white : .black)
//.foregroundColor(task.today ? .blue : .black)
.swipeActions(allowsFullSwipe: true) {
Button(role: .cancel) {
task.done.toggle()
task.today = false
task.date_completion = Date()
do {try viewContext.save()} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
print("mark as done")
} label: {
Label("Done", systemImage: "checkmark")
}
.tint(.green)
}
}
.contentShape(Rectangle())
.buttonStyle(PlainButtonStyle())
.listRowBackground(task.done ? Color.green : task.today ? Color.blue : Color.white)
//.listRowBackground(task.today ? Color.blue : Color.white)
.simultaneousGesture(LongPressGesture()
.onEnded { _ in
let impactMed = UIImpactFeedbackGenerator(style: .light)
impactMed.impactOccurred()
task.today.toggle()
do {try viewContext.save()} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
print("Loooong")
print(task.today)
}
)
.highPriorityGesture(TapGesture()
.onEnded { _ in
isPresented.toggle()
taskDesc = task.desc!
taskUUID = task.id!
print("Tap")
})
.sheet(isPresented: $isPresented, onDismiss: {
isPresented = false
}) {
itemDetail(itemDesc: taskDesc, itemDetail: taskDetail, itemUUID: taskUUID, isPresented: $isPresented)
}
}
.onDelete(perform: deleteItems)
}
//.listStyle(PlainListStyle())
.listRowSeparator(.hidden)
.listRowInsets(.init(top: 4, leading: 8, bottom: 4, trailing: 8))
}
}
mutating func getDoneItemsForThatDate(dateSelected: Date) -> FetchRequest<ToDoItem>{
let calendar = Calendar.current
let startDate = calendar.startOfDay(for: dateSelected)
let endDate = calendar.date(byAdding: .day, value: 1, to: startDate)!
let predicate = NSPredicate(format: "date_completion >= %@ AND date_completion < %@", argumentArray: [startDate, endDate])
return FetchRequest<ToDoItem>(sortDescriptors: [NSSortDescriptor(keyPath: \ToDoItem.timestamp, ascending: false)], predicate: predicate)
}