Search code examples
iosswiftcore-datansfetchedresultscontrollernsfetchrequest

How to write NSFetchRequest with multiple sort descriptors?


I have a Student Entity which has a dateOfBirth attribute.

I want to fetch all Students from the Student Entity in ascending order of their date fo birth but grouped by the decending order of the month.

for example: students which belong to the same Month are grouped together in ascending order but all the groups are in descending order.

Section 1: December 2019
-- student 1: DOB - 1 December 2019
-- student 2: DOB - 2 December 2019
-- student 3: DOB - 3 December 2019
Section 2: November 2019
-- student 1: DOB - 1 November 2019
-- student 2: DOB - 2 November 2019
-- student 3: DOB - 3 November 2019
Section 3: October 2019
-- student 1: DOB - 1 October 2019
-- student 2: DOB - 2 October 2019
-- student 3: DOB - 3 October 2019

Is it possible to write a NSFetchRequest to support this query? I have to use NSFetchResultsController to populate UITableView but I am unable to write a fetch request.

To group the students by their dateOfBirth I have an extra attribute which is a yearMonthString with dateFormat yyyyMM. I am using yearMonthString attribute to group students.

let studentFetchRequest: NSFetchRequest<Student> = Student.fetchRequest()
studentFetchRequest.predicate = NSPredicate(format: "%K != nil AND %K != nil", #keyPath(Student.dateOfBirth), #keyPath(Student.yearMonthString))

let dateSortDescriptor = NSSortDescriptor(key: #keyPath(Student.dateOfBirth), ascending: false)
studentFetchRequest.sortDescriptors = [dateSortDescriptor]

let frc = NSFetchedResultsController<Student>(fetchRequest: studentFetchRequest,
                                              managedObjectContext: managedContext,
                                              sectionNameKeyPath: #keyPath(Student.yearMonthString),
                                              cacheName: nil)

If I give dateSortDescriptor as ascending then all section also become ascending and if I give dateSortDescriptor as descending then students within the section becomes descending.

What is the correct way to write this fetch request? Is it possible to give different sort descriptor for the sections?


Solution

  • Use two sort descriptors, one to sort by the year/month (descending), then another to sort by date of birth (ascending):

    let groupSortDescriptor = NSSortDescriptor(key: #keyPath(Student.yearMonthString), ascending: false)
    let dateSortDescriptor = NSSortDescriptor(key: #keyPath(Student.dateOfBirth), ascending: true)
    studentFetchRequest.sortDescriptors = [groupSortDescriptor, dateSortDescriptor]