NSSortDescriptor问题

我正在制作一个联系簿应用程序,用于从AddressBook获取名称,并将它们存储在Core数据中,并使用NSFetchedResultsController.However在表中显示名称。但是,第一个索引和部分出现在#后面跟着字母表。 但我想要这样做,就像在本地联系应用程序即#索引应该在最后。
我使用了以下的NSortDescriptor

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

这里的“fullName”是通过连接名字和姓氏的核心数据中的key 。 如果fullName不是以字母开头,则节标识符是“fullName”的第一个字母,其节标识符是#。
我已经搜索了它,并在NSortDescriptor比较器中使用NSDiacriticInsensitiveSearch ,但它没有奏效。 如果任何人有任何想法,然后让我知道。

这里是我的代码:

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是实体的对象。


你可以存储额外的属性sortName的实体,这是fullName ,如果名称以字母开头,和<C>fullName ,否则。 <C>是比所有字母“更大”的固定字符。 例如

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

现在,您可以根据sortName进行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;
}

您可以将结果拆分为两个数组,一个以字母字符开头,另一个不是。 然后只需将两者加在一起。 假设您从一组名为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];

你可以这样做:

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

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

链接地址: http://www.djcxy.com/p/36111.html

上一篇: NSSortDescriptor issue

下一篇: NSLocale setPreferredLanguage