My goal:
I want to be able to group CoreData Todo items by their dueDate ranges. ("Today", "Tomorrow", "Next 7 Days", Future")
What I attempted…
I tried using @SectionedFetchRequest
but the sectionIdentifier is expecting a String. If it’s stored in coreData as a Date() how do I convert it for use? I received many errors and suggestions that didn’t help. This also doesn’t solve for the date ranges like "Next 7 Days". Additionally I don’t seem to even be accessing the entity’s dueDate as it points to my ViewModel form instead.
@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'
Ask
Is there another solution that would work better in my case than @SectionedFetchRequest?
if not, I’d like to be shown how to group the data appropriately.
3
Answers
You can make your own
sectionIdentifier
in yourentity
extension
that works with@SectionedFetchRequest
The return variable just has to return something your range has in common for it to work.
Then use it with your
@SectionedFetchRequest
like thisLook at this question too
You can use
Date
too but you have to pick a date to be the section header. In this scenario you can use the upperBound date of your range, just the date not the time because the time could create other sections if they don’t match.And then the request will look like this…
Based on the info you have provided you can test this code by pasting the extensions I have provided into a
.swift
file in your project and replacing your fetch request with the one you want to useIt is throwing the error because that is what you told it to do.
@SectionedFetchRequest
sends a tuple of the type of the section identifier and the entity to theSectionedFetchResults
, so theSectionedFetchResults
tuple you designate has to match. In your case, you wrote:but what you want to do is pass a date, so it should be:
lorem ipsum beat me to the second, and more important part of using a computed variable in the extension to supply the section identifier. Based on his answer, you should be back to:
Please accept lorem ipsum’s answer, but realize you need to handle this as well.
On to the sectioning by "Today", "Tomorrow", "Next 7 Days", etc.
My recommendation is to use a
RelativeDateTimeFormatter
and let Apple do most or all of the work. To create a computed variable to section with, you need to create an extension onTodo
like this:You MUST label the variable as
@objc
, or else Core Data will cause a crash. I think Core Data will be the last place that Obj C lives, but we can pretty easily interface Swift code with it like this.Back in your view, your
@SectionedFetchRequest
looks like this:Then your list looks like this:
You can use this method for achive that,
like this: