核心数据文档指出:
与 [fetched] 属性关联的获取请求可以具有排序顺序,因此可以对获取的属性进行排序。
如何在 Xcode 的数据模型编辑器中为 fetched 属性指定排序描述符?我在任何地方都找不到相关领域。我正在为 iPhone 平台开发,如果这有什么不同的话。
如果通过图形模型编辑器无法做到这一点,我该如何修改代码中 fetched 属性的 fetch 请求,使其具有排序描述符?
您实际上可以获取模型获取的属性并将排序描述符添加到它(再次,在代码中)。如果您选择具有核心数据的模板之一,我会在 XCode 在您的 AppDelegate 中生成的标准方法中执行此操作:
顺便一提。这会对数据模型中所有模型的所有获取的属性进行排序。你可以对它进行幻想和适应,但它是处理对 7 个单独模型进行排序的最简洁的方法,每个模型都获取了需要按名称排序的属性。效果很好。
/**
Returns the managed object model for the application.
If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
*/
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
// Find the fetched properties, and make them sorted...
for (NSEntityDescription *entity in [managedObjectModel entities]) {
for (NSPropertyDescription *property in [entity properties]) {
if ([property isKindOfClass:[NSFetchedPropertyDescription class]]) {
NSFetchedPropertyDescription *fetchedProperty = (NSFetchedPropertyDescription *)property;
NSFetchRequest *fetchRequest = [fetchedProperty fetchRequest];
// Only sort by name if the destination entity actually has a "name" field
if ([[[[fetchRequest entity] propertiesByName] allKeys] containsObject:@"name"]) {
NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]];
[sortByName release];
}
}
}
}
return managedObjectModel;
}
您没有在图形编辑器中指定它们(据我所知)。
您在进行提取的代码中指定它们。
NSFetchRequest* request = [[NSFetchRequest alloc] init];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"whatYouAreLookingFor"
inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
// here's where you specify the sort
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"name" ascending:YES];
NSArray* sortDescriptors = [[[NSArray alloc] initWithObjects: sortDescriptor, nil] autorelease];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:@"myCache"];
建模工具似乎没有办法在获取请求上设置排序描述符。
应该有可能[1] 在加载模型之后但在将其与持久存储协调器关联之前,找到要控制其排序顺序的提取属性描述,并将其提取请求替换为具有排序的提取请求在它们上设置的描述符。
[1] 原则上这应该有效。在实践中,我没有这样做或测试过。
使用 Tim Shadel 的出色答案,我添加了 per-NSManagedObject 子类排序...
...在 Tier.m 中(这是一个 NSManagedObject 子类)...
+ (void)initialize
{
if(self == [Tier class])
{
NSFetchedPropertyDescription *displayLessonPropertyDescription = [[[Tier entityDescription] propertiesByName] objectForKey:@"displayLesson"];
NSFetchRequest *fetchRequest = [displayLessonPropertyDescription fetchRequest];
NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"displayOrder" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]];
[sortByName release];
}
}
对于单个获取的属性,Swift 4,Xcode 9.4:
// retrieve the fetched property's fetch request
let fetchedPropertyRequest = (modelName.entitiesByName["entityName"]!.propertiesByName["fetchedPropertyName"] as! NSFetchedPropertyDescription).fetchRequest
// set up the sort descriptors
let sortDescriptors = [NSSortDescriptor(key: "keyName", ascending: true)]
// add the sort descriptors to the fetch request
fetchedPropertyRequest!.sortDescriptors = sortDescriptors
这是 loooonnnnnnggggggg 的方式:
// retrieve the fetched property's fetch request
let theEntityDescription: NSEntityDescription = modelName.entitiesByName["entityName"]!
let theFetchedPropertyDescription = theEntityDescription.propertiesByName["fetchedPropertyName"]! as! NSFetchedPropertyDescription
let theFetchedPropertyRequest = theFetchedPropertyDescription.fetchRequest
// set up the sort descriptors
let sortDescriptor1 = NSSortDescriptor(key: "keyName", ascending: true)
let theSortDescriptors = [sortDescriptor1]
// add the sort descriptors to the fetch request
theFetchedPropertyRequest!.sortDescriptors = theSortDescriptors
注意:对于这个例子,我强制展开值。确保在实际代码中考虑了可选值!
可悲的是,排序的能力有些有限。例如,您不能获取一个包含数字的 NSString 字段,并对其进行数字排序,至少不能使用 SQLite 后备存储。但是,只要您按字母顺序对字符串进行排序,仅对存储为数字的值进行数字排序等等,应用于获取请求的 NSSortDescriptor 就可以正常工作。
把它放到你的NSManagedObject
子类中:
+ (void)initialize
{
if (self != [EntityManagedObjectSubClass class]) return;
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
NSEntityDescription *entityDescription = [managedObjectModel entitiesByName][@"entityName"];
NSFetchedPropertyDescription *fetchedPropertyDescription = [entityDescription propertiesByName][@"fetchedPropertyName"];
NSFetchRequest *fetchRequest = [fetchedPropertyDescription fetchRequest];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sortDescriptorKey" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
用你自己的东西替换EntityManagedObjectSubClass
, entityName
,fetchedPropertyName
和。sortDescriptorKey
杰夫,如果字符串是右对齐的,你可以对字符串进行排序;“123”>“23”等等。但是 iirc ascii 空格在数字之后,如果是这样,那么您要做的就是创建一个动态属性,它是一个 NSNumber(它支持 compare: 方法),并使用 numberFromString: 方法从字符串中生成一个数字。然后您可以在排序中指定数字字段。在界面中:
@property NSString *stringIsaNumber; // in the data model
@property NSNumber *number;
在实施中:
@dynamic stringIsaNumber;
- (NSNumber *) number ;
{ return [self.stringIsaNumber numberFromString]; }
- (void) setNumber:(NSNumber *)value;
{ self.stringIsaNumber = [NSString stringWithFormat:@"%5i",value) }
ps 请原谅编码错误,这是我的想法。