I have an NSFetchedResultsController
which fetches data from a Core Data structure, a list of albums. It's currently sorted by the artist, so all the A's, B's, etc. I want to add an index so the user can quickly jump to each letter, and I'm using the code below to do it. The issue is that the section headers are now "A", "B", "C", etc., too, meaning I've lost the section headers in alphabetical order with each individual artist on it ("Adele", "America", "Beatles, The", etc.)
I'd like the index to use the letters A through Z, but the section headers to display the artist names in alphabetical order. Pushing a letter in the index would then jump to the first artist with that letter. How can I achieve this (alphabet characters in the index, but a different attribute for the section titles)?
EDIT: If I set my sectionNameKeyPath
to my author
field, the A-Z index is visible, but the letters aren't synced up to the names, for example if I tap S, it takes me to artists beginning with AL, or tapping G takes me to AB. I'm not quite sure why this is, perhaps the section index is screwing up?
Here's the code I'm using:
In my NSManagedObject
subclass:
- (NSString *) firstLetter
{
[self willAccessValueForKey: @"firstLetter"];
NSString *firstLetter = [[[self author] substringToIndex: 1] uppercaseString];
[self didAccessValueForKey: @"firstLetter"];
return firstLetter;
}
In my View Controller, to create the FRC:
NSFetchedResultsController *byAuthorFRC = [[NSFetchedResultsController alloc] initWithFetchRequest: _fetchRequest
managedObjectContext: [[CDManager sharedManager] managedObjectContext]
sectionNameKeyPath: @"firstLetter"
cacheName: nil];
And here's my sectionIndexTitlesForTableView:
method:
- (NSArray *) sectionIndexTitlesForTableView: (UITableView *) tableView
{
return [self.fetchedResultsController sectionIndexTitles];
}
sectionNameKeyPath:@"author"
is the correct parameter, because that is how you
want your table grouped into sections. The standard implementation
- (NSArray *) sectionIndexTitlesForTableView: (UITableView *) tableView
{
return [self.fetchedResultsController sectionIndexTitles];
}
returns the first letter of each section header, so there is no need for a separate
firstLetter
method.
For the correct synchronization from the section index to
the sections you
have to implement the table view data source method tableView:sectionForSectionIndexTitle:atIndex:
. The standard implementation in connection
with a fetched results controller is:
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
Edit:
Swift:
func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
return fetchedResultsController.sectionIndexTitles
}
func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
return fetchedResultsController.sectionForSectionIndexTitle(title, atIndex: index)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With