我遇到了一些麻烦,我想知道是否有人可以提供一些指导。
我正在尝试按以下顺序创建节标题:[“Push”,“Busy”,“Finished”,“Canceled”]。
不幸的是,这个顺序不能通过简单的“升序是/否”来实现...我必须添加一个自定义的比较选择器...这样的东西..:
**“状态”映射到[“推送”,“繁忙”,“完成”,“取消”]的位置
NSSortDescriptor *sortStates = [NSSortDescriptor sortDescriptorWithKey:@"states"
ascending:NO
selector:@selector(compareCustom:)];
因此,我实现了一个“compareCustom” ...但是,事实证明,由于以下异常结果,我无法实现自定义排序器:
***由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“不支持的NSSortDescriptor选择器:compareCustom:”
供参考,sortDate由以下方式实现:
request.sortDescriptors = @[sortStates]
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:@"states"
cacheName:nil];
看来我无法实现一个返回NSComparisonResult的compareCustom吗?我觉得应该有可能。但是我不知道怎么做。如果有人可以提供一些建议,我将不胜感激!
还供参考,这是我的“compareCustom”方法
-(NSComparisonResult)compareCustom:(NSString *)anotherState {
if ([(NSString *)self isEqualToString:@"Push"] && [anotherState isEqualToString:@"Canceled"]) {
return NSOrderedDescending;
}
else if ([(NSString *)self isEqualToString:@"Push"] && [anotherState isEqualToString:@"Busy"]) {
return NSOrderedDescending;
}
else if ([(NSString *)self isEqualToString:@"Push"] && [anotherState isEqualToString:@"Finished"]) {
return NSOrderedDescending;
}
else if ([(NSString *)self isEqualToString:@"Push"] && [anotherState isEqualToString:@"Push"]) {
return NSOrderedSame;
}
else if ([(NSString *)self isEqualToString:@"Finished"] && [anotherState isEqualToString:@"Canceled"]) {
return NSOrderedDescending;
}
else if ([(NSString *)self isEqualToString:@"Finished"] && [anotherState isEqualToString:@"Busy"]) {
return NSOrderedAscending;
}
else if ([(NSString *)self isEqualToString:@"Finished"] && [anotherState isEqualToString:@"Finished"]) {
return NSOrderedSame;
}
else if ([(NSString *)self isEqualToString:@"Finished"] && [anotherState isEqualToString:@"Push"]) {
return NSOrderedAscending;
}
else if ([(NSString *)self isEqualToString:@"Busy"] && [anotherState isEqualToString:@"Finished"]) {
return NSOrderedDescending;
}
else if ([(NSString *)self isEqualToString:@"Busy"] && [anotherState isEqualToString:@"Canceled"]) {
return NSOrderedDescending;
}
else if ([(NSString *)self isEqualToString:@"Busy"] && [anotherState isEqualToString:@"Busy"]) {
return NSOrderedSame;
}
else if ([(NSString *)self isEqualToString:@"Busy"] && [anotherState isEqualToString:@"Push"]) {
return NSOrderedAscending;
}
else {
return NSOrderedSame;
}
}
最佳答案
根据documentation的自定义排序不适用于SQLite持久存储:
另一方面,SQL存储会编译谓词和排序
SQL的描述符,并在数据库本身中评估结果。
这样做主要是为了提高性能,但这意味着评估
发生在非可可环境中,因此对描述符进行排序(或
谓词)依靠可可就行不通。支持的排序
选择器是compare:和caseInsensitiveCompare :、 localizedCompare :、
localizedCaseInsensitiveCompare:和localizedStandardCompare:(
后者是类似Finder的排序方式,大多数人应该使用
时间)。另外,您不能使用
SQLite存储。
因此,看来您不能简单地强制NSFetchedResultsController
以字母顺序以外的方式显示节。
但是您可以使用解决方法。向您的实体添加其他整数类型的持久属性(我们将其称为sectionOrder
)。根据states
属性设置其值(因此"Push"
的值为0,"Busy"
的值为1。)例如,您可以在awakeFromInsert
方法中进行设置。
然后在排序描述符中将@"sectionOrder"
用作sectionNameKeyPath
和键路径。您可以使用此UITableViewDataSource
方法将板块标题设置为“推”,“忙”等:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.controller sections] objectAtIndex:section];
return [sectionInfo.objects.firstObject name];
}
归功于excellent answer。