如何对Core Data获取的属性进行排序

时间:2009-07-01 23:09:17

标签: iphone xcode sorting core-data fetched-property

Core Data Documentation表示:

  

与[fetched]属性关联的提取请求可以具有排序顺序,因此可以对已提取的属性进行排序。

如何在Xcode的数据模型编辑器中指定fetched属性的排序描述符?我无法在任何地方找到相关领域。我正在为iPhone平台开发,如果这有任何不同。

如果通过图形模型编辑器无法做到这一点,我该如何在代码中修改fetched属性的获取请求,以便它有一个排序描述符?

8 个答案:

答案 0 :(得分:35)

您实际上可以获取模型获取属性并向其添加排序描述符(同样,在代码中)。如果您选择其中一个带有核心数据的模板,我在您的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;
}

答案 1 :(得分:13)

您没有在图形编辑器中指定它们(据我所知)。

您可以在进行提取的代码中指定它们。

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"];

答案 2 :(得分:5)

建模工具似乎没有办法在获取请求中设置排序描述符。

在加载模型之后但在与持久性存储协调器关联之前,应该可以[1]找到要为其控制排序顺序的已获取属性描述,并用获取请求替换它们的获取请求在它们上面设置了排序描述符。

[1]原则上这应该有效。在实践中,我还没有这样做或测试过它。

答案 3 :(得分:5)

使用Tim Shadel的好答案我添加了每个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];
    }
}

答案 4 :(得分:0)

但遗憾的是,排序能力有限。例如,您不能采用包含数字的NSString字段,并对其进行数字排序,至少不能使用SQLite后备存储。只要您按字母顺序对字符串进行排序,数字上只对存储为数字等的值进行排序,但应用于获取请求的NSSortDescriptor工作正常。

答案 5 :(得分:0)

将它放入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]];
}

EntityManagedObjectSubClassentityNamefetchedPropertyNamesortDescriptorKey替换为您自己的内容。

答案 6 :(得分:0)

对于单个获取的属性,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

注意:对于此示例,我强制展开了值。 确保您在实际代码中考虑了可选值!

答案 7 :(得分:-1)

杰夫,如果字符串是右对齐的,你可以对字符串进行排序; “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 plz原谅编码错误,这是我的头脑。