How do I change the display order of sections in a UITableview populated from an NSFetchedResultsControler?

I was wondering if anyone knew the best solution to defining a custom display order for the sections in a UITableView - I am loading the data using Core Data and an NSFetchedResultsControler, and I am successfully using NSSortDescriptors and also successfully grouping the items returned into sections using sectionNameKeyPath:

So far so good BUT - the sections are listed in alphabetical order and I would like to override this and order the sections in a specific custom sort order.

For example if I had a Entity called Item with an attribute called colour and I used this colour attribute as the sectionNameKeyPath: how would I then order the sections in a specific way - currently the sections display as

Blue, Green, Indigo, Orange, Red, Violet, Yellow.

  • because they have an NSortDescriptor applied to the NSFetchedResultsController (which I have defined). BUT how could I reorder these sections in a specific way to display the sections like so -

Red, Orange, Yellow, Green, Blue, Indigo, Violet.

My NSFetchedResultsController code follows -

- (NSFetchedResultsController *)fetchedResultsController {

    if (fetchedResultsController_ != nil) {
        return fetchedResultsController_;
    }

    /*
     Set up the fetched results controller.
    */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.

    NSSortDescriptor *colourDescriptor = [[NSSortDescriptor alloc] initWithKey:@"colour" ascending:YES];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:colourDescriptor, sortDescriptor, nil];

    [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:@"colour" cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [colourDescriptor release];
    [sortDescriptors release];

    NSError *error = nil;
    if (![fetchedResultsController_ performFetch:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return fetchedResultsController_;
}

I understand the examples posted regarding using a custom subclass of NSManagedObject and a getter method to dynamically assign a property to be used as the sectionNameKeyPath: but the examples for these still tend to provide section names which are then listed alphabetically.

It's clearly me being new to this but any suggestions/direction would be greatly appreciated.

Answers


To provide a custom sort order to sections you need to subclass NSFetchedResultsController.

From the NSFetchedResultsController class docs:

You create a subclass of this class if you want to customize the creation of sections and index titles. You override sectionIndexTitleForSectionName: if you want the section index title to be something other than the capitalized first letter of the section name. You override sectionIndexTitles if you want the index titles to be something other than the array created by calling sectionIndexTitleForSectionName: on all the known sections.

It's kind of tucked away so you miss the first couple of times you read about the class.

To implement, get the fetched results controller's section attribute which is an array of section names sorted alphabetically, then return the right element for the index of the tableview section.


Instead of storing the string "Red", "Orange", "Yellow" etc, store enum values that represents the colors. So store 0 for red and 1 for orange, etc. Then it will be sorted correctly. When when you want to display the header for the section use the enum to figure out which color it is and find the correct string.


Need Your Help

UIScrollView jumps down when first touched

iphone ios cocoa-touch uiscrollview

I have two UIScrollViews, one horizontal, one vertical, both two pages each (as in, the horizontal one is two pages wide, and the vertical one is two pages high). The horizontal scrollview is in the

Seem more..issue (Operation slows down after clicking see more 5-10 times)

javascript jquery

Seem more..issue (Operation slows down after clicking see more 5-10 times)