NSSortDescriptor issue

前端 未结 4 2010
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-13 20:24

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

4条回答
  •  难免孤独
    2021-01-13 21:08

    You could store an additional attribute sortName in the entity, which is fullName if the name starts with a letter, and fullName 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;
    }
    

提交回复
热议问题