4

我正在制作一个通讯录应用程序,我从地址簿中获取名称并将它们存储在核心数据中,并使用NSFetchedResultsController.However第一个索引在表格上显示名称,出现的部分是 # 后跟字母。但我想像在本机联系人应用程序中那样做,即 #index 应该最后出现。
我使用了以下内容NSortDescriptor

sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"fullName" 升序:YES ];

这里的“fullName”是key通过连接名字和姓氏组成的核心数据。并且节标识符是“fullName”的第一个字母,如果fullName不以字母开头,则其节标识符是#。
我已经搜索过它并NSDiacriticInsensitiveSearchNSortDescriptor比较器中使用了它,但它没有用。如果有人有任何想法,请告诉我。

这是我的代码:

NSString *special = @"\uE000";
if ([[self sectionName:contactName] isEqualToString:@"#"]) {                           
    sortName = [special stringByAppendingString:contactName];
}
else{
    sortName = contactName;
}
[newContact setValue:[self sectionIdentifier:sortName] forKey:@"sectionIdentifier"];
[newContact setValue:sortName forKey:@"sortName"];

这是排序描述符:

sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sortName" ascending:YES];

[self sectionIdentifier:sortName]如果 sortName 以非字母开头,则此方法返回 #,否则返回其开头的字母。

newContact 是实体的对象。

4

4 回答 4

6

sortName您可以在实体中存储一个附加属性,即fullName名称是否以字母开头,<C>fullName否则。<C>是一个比所有字母“更大”的固定字符。例如

NSString *special = @"\uE000";
if ("fullName starts with letter")
    sortName = fullName;
else
    sortName = [special stringByAppendingString:fullName];

现在您可以根据 进行排序,如果以特殊字符开头,sortName则部分标识符将为“#” 。sortName

缺点是您必须存储一个附加属性,优点是您可以继续使用获取的结果控制器(它只能使用持久属性进行排序)。

更新:实际上可以做得更容易一些。

创建新条目时,sectionIdentifier如果是字母,则设置为名称的第一个字符,否则设置为特殊字符:

NSString *special = @"\uE000";

if ([[NSCharacterSet letterCharacterSet] characterIsMember:[contact.contactName characterAtIndex:0]]) {
    contact.sectionIdentifier = [contact.contactName substringToIndex:1];
} else {
    contact.sectionIdentifier = special;
}

获取的结果控制器sectionIdentifier用于对部分进行分组和排序。每个部分中的条目按以下顺序排序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];

所有非字母条目现在都归入最后一部分。最后一步是显示#最后一节的正确节标题:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.frc sections] objectAtIndex:section];
    NSString *title = [sectionInfo name];
    if ([title isEqualToString:special])
        title = @"#";
    return title;
}
于 2012-10-17T18:24:05.297 回答
2

您可以将结果分成两个数组,一个以字母字符开头,一个不以字母字符开头。然后只需将两者相加即可。假设您从一个名为的托管对象数组开始results

//Create the sort descriptor array
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"fullName" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:sd];

//Create a sorted array of objects where fullName starts with an alpha character
//using a Regex

NSPredicate *pred = [NSPredicate predicateWithFormat:@"fullName MATCHES '^[a-zA-Z].*'"];

NSArray *alpha = [[results filteredArrayUsingPredicate:pred] sortedArrayUsingDescriptors:descriptors];

//Now use the alpha array to create an array of objects where the fullName does not
//start with an alpha character

NSMutableArray *nonAlpha = [results mutableCopy];

[nonAlpha removeObjectsInArray:alpha];

[nonAlpha sortUsingDescriptors:descriptors];

//Now put them back together again

NSArray *sortedResults = [alpha arrayByAddingObjectsFromArray:nonAlpha];

//And if you're not using ARC!
[nonAlpha release];
于 2012-10-12T19:58:56.020 回答
1

你可以这样做:

sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];

只要确保它不会影响您的情况下的性能。

于 2012-10-09T12:56:02.513 回答
0

您可以尝试编写自己的比较器功能

假设它正在对 ManagedObjects 进行排序并且它们都具有 fullName 作为字段,那么以下内容可能会有所帮助。

[[NSSortDescriptor alloc] initWithKey:@"FullName" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
        return [[obj1 objectForKey:@"fullName"] compare:[obj2 objectForKey:@"fullName"] options:NSCaseInsensitiveSearch];
    }];

这样做的好处是您还可以为每次比较编写 NSLog 并查看发生了什么。

于 2012-10-12T04:39:57.700 回答