Josh Kahane
Josh Kahane

Reputation: 17169

CoreData NSFetchedResultsController Sorting

I have a small problem with sorting my NSFetchedResultsController.

My NSManagedObject has two attributes. date and startTime.

The date is of time 00:00:00 on all my objects, this way when using date as the sectionNameKeyPath it grabs all the objects with identical dates (by day) into one section. If the time of the dates were different, it would put every object into a different section.

This works well, but then inside each group I want to sort the objects by startTime. So they are list from earliest on that date to the latest in each section respectively.

My issue is when using date as the sectionNameKeyPath and startTime as an NSSortDescriptor` it doesn't like it and plays weirdly. Such as only sometimes showing certain data in what seems like an irregular way.

I think it comes down to having to have the sort descriptor and sectionNameKeyPath the same. Am I right in thinking this? If not, how should I setup my NSFetchedResultsController to list my data in the fashion mentioned?

Thanks.

EDIT: Here is come code... Also worth noting when using startTime as my second sort descriptor, it causes duplicates to display in my tableview with nil objects.

NSFetchedResultsController:

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];
    NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"startTime" ascending:YES];
    NSArray *sortDescriptors = @[sortDescriptor1, sortDescriptor2];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"date" cacheName:@"Master"];

cellForRowAtIndexPath just a snippet showing how I designate each managed object:

id <NSFetchedResultsSectionInfo> sectionInfo = [self.flightFetchedResultsController.sections objectAtIndex:indexPath.section];
    NSArray *sectionFlights = [sectionInfo objects];
    Flight *flight = [sectionFlights objectAtIndex:indexPath.row];

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return self.flightFetchedResultsController.sections.count;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.flightFetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

Upvotes: 2

Views: 1252

Answers (1)

Fogmeister
Fogmeister

Reputation: 77661

Your section key name path needs to match the first sort descriptor.

So you could do...

// sectionKeyNamePath = @"date".

NSSortDescriptor *dateSD = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES];
NSSortDescriptor *startTimeSD = [NSSortDescriptor sortDescriptorWithKey:@"startTime" ascending:YES];

frc.request.sortDescriptors = @[dateSD, startTimeSD];

If you do this then it will sort (and section) by date and then sort each section by startTime.

From your code

You are getting the fetched objects incorrectly.

To get an object you need to use...

Flight *flight = [self.frc objectAtIndexPath:indexPath];

A fetched results controller knows about its sections and rows. You don't need to split it apart.

Upvotes: 5

Related Questions