Grouping CoreData by Date() in SwiftUI List as sections(按日期()将SWIFTUI列表中的CoreData分组为节)
问题描述
我的目标:
我希望能够按CoreData待办事项的过期范围对其进行分组。(今天&q;、明天&q;、未来7天&q;)
我尝试的内容.
我尝试使用@SectionedFetchRequest
,但sectionIdentifier需要字符串。如果它作为日期()存储在CoreData中,我如何转换它以供使用呢?我收到了许多错误和建议,但都无济于事。这也不适用于日期范围,如&Quot;NEXT 7 DATE&QOOT;。此外,我似乎甚至没有访问实体的duedate,因为它指向我的ViewModel表单。
@Environment(.managedObjectContext) private var viewContext
//Old way of fetching Todos without the section fetch
//@FetchRequest(sortDescriptors: []) var todos: FetchedResults<Todo>
@SectionedFetchRequest<String, Todo>(
entity: Todo.entity(), sectionIdentifier: Todo.dueDate,
SortDescriptors: [SortDescriptor(.Todo.dueDate, order: .forward)]
) var todos: SectionedFetchResults<String, Todo>
Cannot convert value of type 'KeyPath<Todo, Date?>' to expected argument type 'KeyPath<Todo, String>'
Value of type 'NSObject' has no member 'Todo'
询问
有没有比@SectionedFetchRequest?
更适合我的情况的解决方案。如果没有,我希望看到如何对数据进行适当分组。
推荐答案
您可以在entity
extension
中制作您自己的sectionIdentifier
,@SectionedFetchRequest
返回变量只需返回您的范围共有的内容,它才能正常工作。
extension Todo{
///Return the string representation of the relative date for the supported range (year, month, and day)
///The ranges include today, tomorrow, overdue, within 7 days, and future
@objc
var dueDateRelative: String{
var result = ""
if self.dueDate != nil{
//Order matters here so you can avoid overlapping
if Calendar.current.isDateInToday(self.dueDate!){
result = "today"//You can localize here if you support it
}else if Calendar.current.isDateInTomorrow(self.dueDate!){
result = "tomorrow"//You can localize here if you support it
}else if Calendar.current.dateComponents([.day], from: Date(), to: self.dueDate!).day ?? 8 <= 0{
result = "overdue"//You can localize here if you support it
}else if Calendar.current.dateComponents([.day], from: Date(), to: self.dueDate!).day ?? 8 <= 7{
result = "within 7 days"//You can localize here if you support it
}else{
result = "future"//You can localize here if you support it
}
}else{
result = "unknown"//You can localize here if you support it
}
return result
}
}
然后将其与您的@SectionedFetchRequest
一起使用,如下所示
@SectionedFetchRequest(entity: Todo.entity(), sectionIdentifier: .dueDateRelative, sortDescriptors: [NSSortDescriptor(keyPath: Todo.dueDate, ascending: true)], predicate: nil, animation: Animation.linear)
var sections: SectionedFetchResults<String, Todo>
也查看this question
您也可以使用Date
,但您必须选择一个日期作为节标题。在此方案中,您可以使用范围的上行日期,只使用日期而不是时间,因为如果它们不匹配,时间可能会创建其他部分。
extension Todo{
///Return the upperboud date of the available range (year, month, and day)
///The ranges include today, tomorrow, overdue, within 7 days, and future
@objc
var upperBoundDueDate: Date{
//The return value has to be identical for the sections to match
//So instead of returning the available date you return a date with only year, month and day
//We will comprare the result to today's components
let todayComp = Calendar.current.dateComponents([.year,.month,.day], from: Date())
var today = Calendar.current.date(from: todayComp) ?? Date()
if self.dueDate != nil{
//Use the methods available in calendar to identify the ranges
//Today
if Calendar.current.isDateInToday(self.dueDate!){
//The result variable is already setup to today
//result = result
}else if Calendar.current.isDateInTomorrow(self.dueDate!){
//Add one day to today
today = Calendar.current.date(byAdding: .day, value: 1, to: today)!
}else if Calendar.current.dateComponents([.day], from: today, to: self.dueDate!).day ?? 8 <= 0{
//Reduce one day to today to return yesterday
today = Calendar.current.date(byAdding: .day, value: -1, to: today)!
}else if Calendar.current.dateComponents([.day], from: today, to: self.dueDate!).day ?? 8 <= 7{
//Return the date in 7 days
today = Calendar.current.date(byAdding: .day, value: 7, to: today)!
}else{
today = Date.distantFuture
}
}else{
//This is something that needs to be handled. What do you want as the default if the date is nil
today = Date.distantPast
}
return today
}
}
然后请求将如下所示.
@SectionedFetchRequest(entity: Todo.entity(), sectionIdentifier: .upperBoundDueDate, sortDescriptors: [NSSortDescriptor(keyPath: Todo.dueDate, ascending: true)], predicate: nil, animation: Animation.linear)
var sections: SectionedFetchResults<Date, Todo>
根据您提供的信息,您可以测试此代码,方法是将我提供的扩展粘贴到项目的.swift
文件中,并将获取请求替换为您要使用的请求
这篇关于按日期()将SWIFTUI列表中的CoreData分组为节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!