Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c NSSortDescriptor问题_Objective C_Xcode_Core Data_Nsfetchedresultscontroller - Fatal编程技术网

Objective c NSSortDescriptor问题

Objective c NSSortDescriptor问题,objective-c,xcode,core-data,nsfetchedresultscontroller,Objective C,Xcode,Core Data,Nsfetchedresultscontroller,我正在制作一个通讯录应用程序,从通讯录中提取姓名,并将其存储在核心数据中,然后使用NSFetchedResultsController将姓名显示在表格上。然而,出现的第一个索引和部分是字母表。但我想像在本机联系人应用程序中那样做,即#索引最终应该出现。 我使用了以下传感器描述程序: sortDescriptor=[[NSSortDescriptor alloc]initWithKey:@“全名”升序:是] 这里的“全名”是核心数据中的键,它由名字和姓氏连接而成。 节标识符是“全名”的第一个字母如

我正在制作一个通讯录应用程序,从通讯录中提取姓名,并将其存储在核心数据中,然后使用
NSFetchedResultsController将姓名显示在表格上。然而,
出现的第一个索引和部分是字母表。但我想像在本机联系人应用程序中那样做,即#索引最终应该出现。
我使用了以下
传感器描述程序

sortDescriptor=[[NSSortDescriptor alloc]initWithKey:@“全名”升序:是]

这里的“全名”是核心数据中的
,它由名字和姓氏连接而成。 节标识符是“全名”的第一个字母如果
fullName
不是以字母开头,则其节标识符是#。
我搜索过它,并在
传感器描述器
比较器中使用了
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是实体的对象。

您可以执行以下操作:

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

请确保它不会影响您的性能。

您可以尝试编写自己的比较器函数

假设它正在对ManagedObject进行排序,并且它们都以全名作为字段,那么下面的内容可能会有所帮助

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

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

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

您可以在实体中存储一个附加属性
sortName
,如果名称以字母开头,则该属性为
fullName
,否则为
fullName
<代码>是一个固定字符,它比所有字母都“大”。比如说

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;
}
-(NSString*)表视图:(UITableView*)表视图标题标题标题部分:(NSInteger)部分{
id sectionInfo=[[self.frc sections]objectAtIndex:section];
NSString*标题=[sectionInfo名称];
if([标题IsequalString:特殊])
标题=@“#”;
返回标题;
}

我尝试了您的方法,但它没有返回正确的节名和名称index@user1632153:你能把你的代码(或简化的示例项目)放在我可以下载的地方吗?我会尝试找出一个解决方案。@user1632153:请查看我的更新答案。我自己测试过,它似乎很有效,所以我希望它能对您有所帮助。@Martin R我自己的测试表明,
tableView:titleForHeaderInSection:
方法在
NSFetchedResultsController
初始化为非nil
sectionNameKeyPath
时根本不会被调用。因此,这个特殊字符不会被#替换。@JohnTopley:我不能确认,它在我的测试项目中(使用sectionNameKeyPath)起了作用。也许您有一个优先的
viewForHeaderInSection
方法?使用此方法会导致应用程序崩溃这是在调试器中提供的:不支持的NSSortDescriptor(不支持比较器块)