I am making a contact book App where I am fetching names from AddressBook and stored them in Core data and displayed the names on a table using NSFetchedResultsControl
You could store an additional attribute sortName
in the entity, which is fullName
if the name starts with a letter, and
otherwise.
is a fixed character which is "greater" than all letters. For example
NSString *special = @"\uE000";
if ("fullName starts with letter")
sortName = fullName;
else
sortName = [special stringByAppendingString:fullName];
Now you can sort according to sortName
, and the section identifier would be "#" if sortName
starts with the special character.
The disadvantage is that you have to store an additional attribute, the advantage is that you can continue to use a fetched results controller (which can use only persistent attributes for sorting).
UPDATE: It can actually be done a bit easier.
When you create a new entry, you set sectionIdentifier
to the first character of the name if it is a letter, and to the special character otherwise:
NSString *special = @"\uE000";
if ([[NSCharacterSet letterCharacterSet] characterIsMember:[contact.contactName characterAtIndex:0]]) {
contact.sectionIdentifier = [contact.contactName substringToIndex:1];
} else {
contact.sectionIdentifier = special;
}
The fetched results controller uses sectionIdentifier
for grouping and sorting the sections. Entries within each section are sorted by contactName
:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Contact"];
NSSortDescriptor *sort1 = [NSSortDescriptor sortDescriptorWithKey:@"sectionIdentifier"
ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:@"contactName"
ascending:YES selector:@selector(localizedStandardCompare:)];
[request setSortDescriptors:@[sort1, sort2]];
self.frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.context
sectionNameKeyPath:@"sectionIdentifier"
cacheName:nil];
All non-letter entries are now grouped in the last section. The final step is to display the correct section header #
for the last section:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
id sectionInfo = [[self.frc sections] objectAtIndex:section];
NSString *title = [sectionInfo name];
if ([title isEqualToString:special])
title = @"#";
return title;
}