I have a NSFetchedResultsController
that feeds a UITableViewController
with Appointment
entities that have, among others, a property dateTime
.
My goal is to have a list of appointments sorted like this:
In other words:
First sort on whether it's before or after today, then on dateTime
. So first sort on (dateTime > %TODAY%)
, then on dateTime
itself (future ascending, past descending).
Is there any way to do this? My problem is that I can't use %TODAY% in a sort descriptor, but maybe there's another way to achieve the same visual result.
UPDATE: Be aware the accepted answer is not possible with a NSFetchedResultsController
. I chose another solution, ordering the Appointments
before showing the view., saving that to the database, and let the NSFetchedResultsController
pick up the changes.
UPDATE 2: Accepted answer did to do exactly what I wanted. My implementation:
let futureAppointments = appointments.filter({ $0.dateTime != nil && $0.dateTime?.compare(Date()) == .orderedDescending })
.sorted(by: { $0.dateTime?.compare($1.dateTime! as Date) == .orderedAscending })
let pastAppointments = appointments.filter({ $0.dateTime != nil && $0.dateTime?.compare(Date()) == .orderedAscending })
.sorted(by: { $0.dateTime?.compare($1.dateTime! as Date) == .orderedDescending })
let sorted = futureAppointments + pastAppointments
for (index, appointment) in sorted.enumerated() {
appointment.order = NSNumber(integerLiteral: index)
}
It's only idea. May be you can create sortdescriptor like this:
NSSortDescriptor(key: "test", ascending: true) { (v1, v2) -> ComparisonResult in
guard let d1 = v1 as? Date else
{
return .orderedAscending
}
guard let d2 = v2 as? Date else
{
return .orderedAscending
}
if abs(d1.timeIntervalSinceNow) < abs(d2.timeIntervalSinceNow) { return .orderedAscending }
if abs(d1.timeIntervalSinceNow) > abs(d2.timeIntervalSinceNow) { return .orderedDescending }
return .orderedSame
}
I think it will be work.