Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSFetchedResultsController - different sort order than section name

I have an NSManagedObject for the sections in the grouped UITableView. This object has the attributes "name" and "createdAt". I want to use "name" in te UI for the section titles, but sorted by "createdAt". According to the documentation the first sortDescriptor key has to be also the sectionNameKeyPath of the NSFetchedResultsController.

I suggested using two sortDescriptors, but it doesn't work. The sections are still sorted by name.

- (NSFetchedResultsController *)fetchedResultsController {
  if (_fetchedResultsController != nil) {
      return _fetchedResultsController;
  }

  NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
  NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:[CoreDataHelper instance].managedObjectContext];
  [fetchRequest setEntity:entity];

  NSSortDescriptor *sortName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
  NSSortDescriptor *sortDate = [[NSSortDescriptor alloc] initWithKey:@"createdAt" ascending:YES];

  [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortName, sortDate, nil]];

  [fetchRequest setFetchBatchSize:20];

  NSFetchedResultsController *theFetchedResultsController =
  [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:[CoreDataHelper instance].managedObjectContext sectionNameKeyPath:@"name"
                                               cacheName:@"Root"];
  self.fetchedResultsController = theFetchedResultsController;

  return _fetchedResultsController;
}
like image 479
Sebastian Avatar asked Sep 29 '12 22:09

Sebastian


1 Answers

A fetched results controller (FRC) uses only the first sort descriptor to group (and sort) the objects into sections. A second sort descriptor can be added to sort the objects within each section.

Also, the key path of the sort descriptor must be the same as the sectionNameKeyPath of the FRC (or at least generate the same relative ordering).

See also Creating a Fetched Results Controller in the “Core Data Programming Guide”:

... In this example you add one more NSSortDescriptor instance to the NSFetchRequest instance. You set the same key from that new sort descriptor as the sectionNameKeyPath on the initialization of the NSFetchedResultsController. The fetched results controller uses this initial sort controller to break apart the data into multiple sections and therefore requires that the keys match.

In your case, you can proceed as follows:

  1. Use createdAt as sectionNameKeyPath and in the first sort descriptor.

  2. Modify the titleForHeaderInSection delegate function to return the name property instead of createdAt:

     - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
         id <NSFetchedResultsSectionInfo> sectionInfo = [[self.controller sections] objectAtIndex:section];
         return [[[sectionInfo objects] objectAtIndex:0] name];
     }
    

Note: If you have multiple objects with the same name but different createAt values, these will be grouped into different sections with the above approach. I don't know if that is a problem for you.

like image 121
Martin R Avatar answered Nov 09 '22 03:11

Martin R