如何对核心数据获取的属性进行排序

发布于 2024-07-26 03:13:13 字数 419 浏览 8 评论 0原文

核心数据文档指出:

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

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

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

The Core Data Documentation states that:

The fetch request associated with the [fetched] property can have a sort ordering, and thus the fetched property may be ordered.

How do I specify the sort descriptors for the fetched property in Xcode's data model editor? I can't find a relevant field anywhere. I'm developing for the iPhone platform, if this makes any difference.

If this is not possible via the graphical model editor, how do I go about modifying the fetch request for the fetched property in code so that it has a sort descriptor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

勿忘心安 2024-08-02 03:13:13

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

You can actually grab the model fetched property and add the sort descriptors to it (again, in code). I did this in the standard method that XCode generates in your AppDelegate if you choose one of the templates with Core Data:

By the way. This sorts ALL fetched properties on ALL models in your data model. You could get fancy and adaptive with it, but it was the most succinct way to handle sorting the 7 separate models that each had fetched properties that needed to be sorted by name. Works well.

/**
 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;
}
魂ガ小子 2024-08-02 03:13: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"];

You don't specify them in the graphical editor (as far as I know).

You specify them in the code where you make the fetch.

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"];
野心澎湃 2024-08-02 03:13:13

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

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

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

The modeling tool doesn't appear to have a way to set the sort descriptors on the fetch request.

It should be possible[1] to, after loading the model but before associating it with a persistent store coordinator, to find the fetched property descriptions for which you want to control the sort order, and replace their fetch requests with fetch requests that have sort descriptors set on them.

[1] In principle this should work. In practice, I have not done so or tested it.

鹿港巷口少年归 2024-08-02 03:13:13

使用 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];
    }
}

Using Tim Shadel's great answer I added per-NSManagedObject subclass sorting...

...in Tier.m (which is a NSManagedObject subclass)...

+ (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];
    }
}
过潦 2024-08-02 03:13:13

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

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

For a single fetched property, 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

Here's the same thing the loooonnnnnnggggggg way:

// 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

Note: for this example, I force-unwrapped values. Make sure that you account for optional values in your actual code!

素手挽清风 2024-08-02 03:13:13

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

Sadly, though, the ability to sort is somewhat limited. For example, you cannot take a field that is an NSString containing a number, and sort it numerically, at least not with a SQLite backing store. As long as you are sorting alphabetically on strings, numerically only on values stored as numbers and so forth, though, the NSSortDescriptor applied to the fetch request works just fine.

甜味超标? 2024-08-02 03:13:13

将其放入您的 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用你自己的东西。

Put this into your NSManagedObject subclass:

+ (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]];
}

Replace EntityManagedObjectSubClass, entityName, fetchedPropertyName and sortDescriptorKey with your own stuff.

魔法少女 2024-08-02 03:13:13

Jeff,如果字符串是右对齐的,你可以只对字符串进行排序; “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 请原谅编码错误,这超出了我的想象。

Jeff, if the strings are right-aligned, you could just sort on the strings; " 123" > " 23" and so on. But iirc ascii space is after the numbers, and if so, then what you would do is create a dynamic property that is an NSNumber (which supports the compare: method), and use the numberFromString: method to make a number from the string. Then you can specify the number field in the sort. In the interface:

@property NSString *stringIsaNumber; // in the data model
@property NSNumber *number;

in the implementation:

@dynamic stringIsaNumber; 
- (NSNumber *) number ;
{ return [self.stringIsaNumber numberFromString]; }
- (void) setNumber:(NSNumber *)value;
{ self.stringIsaNumber = [NSString stringWithFormat:@"%5i",value) }

ps plz forgive coding errors, this is off the top of my head.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文