What is the best way to sort a Core Data Entity?

15,008

Your question is quite general but I'll try to give you some hints.

When you use NSFetchRequest class you can specify sort descriptors.

From Apple doc:

An array of sort descriptors (instances of NSSortDescriptor) that specify how the returned objects should be ordered, for example by last name then by first name.

Here you can find a simple example within Core Data Snippets doc

NSManagedObjectContext *context = <#Get the context#>;

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"<#Entity name#>"
    inManagedObjectContext:context];
[fetchRequest setEntity:entity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"<#Sort key#>"
    ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
    // Handle the error
}

// release allocated objects if you don't use ARC

Where

<#Entity name#> is the name of the entity you want to retrieve, e.g. Manager.

<#Sort key#> is the name of the key the request will use to order, e.g. name is an attribute of Manager entity.

So, in my example:

NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"name"
    ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByName, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

Since setSortDescriptors: sets an array of sort descriptors, you can specify multiple keys against you want to order. e.g. specify to order against name and salary. The sort descriptors are applied in the order in which they appear in the sortDescriptors array. So, in my example, first by name and then by salary.

So, in my example, it could become

NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"name"
    ascending:YES];
NSSortDescriptor *sortBySalary = [[NSSortDescriptor alloc] initWithKey:@"salary"
    ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByName, sortBySalary, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

Hope that helps.

Edit

Since fetchedObjects contains NSManagedObject (I suppose you did not change the result type of your request) you need to iterate like the following:

for(NSManagedObject* currentObj in fetchedObjects) {

    NSLog(@"Print the name %@", [currentObj valueForKey:@"name"]);
}

So, you need to access attributes or relationships through Key Value Coding. To make your life easier you could think to create NSManagedObject subclasses for the entities you created like organising-core-data-for-ios.

Share:
15,008
Alex Godbehere
Author by

Alex Godbehere

Hobbyist Programmer. Studying Systems Engineering at University of Sheffield.

Updated on June 21, 2022

Comments

  • Alex Godbehere
    Alex Godbehere almost 2 years

    I have a fully working core data model, but when I return the data using a fetch request, it's in a seemingly random order. What is the best way to sort this data? Is it to use another table in the Core Data model, and 'query' the first? Or would it be to pull down the data into an array, and sort it that way?

    I'm not too sure how to do either of these, which is the reason that I am asking this question.

  • Alex Godbehere
    Alex Godbehere almost 12 years
    Excellent, just what I needed. Thanks!
  • Alex Godbehere
    Alex Godbehere almost 12 years
    Just a quick one. How do I now access each 'entry' from the array? For example if I sorted by price, ascending, how would I select that one entry and access other fields (name, brand, etc...). My guess would be to use a for * in * loop, but i'm not sure what I would use as the data type. The code I have now is: for (NSString *data in fetchedObjects) { NSLog(@"%@",data); } But I somehow think this is wrong.
  • iOS-Coder
    iOS-Coder almost 11 years
    @flexaddicted Thanks for your example, which helped me while I was struggling with some code. By the way, do you happen to know the MagicalRecord framework (see: github.com/magicalpanda/MagicalRecord), with which CoreData stuff can be made fairly easy and with less code?.
  • Lorenzo B
    Lorenzo B almost 11 years
    @iOS-Coder Sorry, I cannot understand your question. Could you explain what you mean? Thanks.
  • iOS-Coder
    iOS-Coder almost 11 years
    @flexaddicted Actually it was not meant as a question, but rather a suggestion on how to start quickly (with minimal coding) in programming with CoreData.
  • Lorenzo B
    Lorenzo B almost 11 years
    @iOS-Coder I don't know MR. But yes, I think it's easy to use since it's a wrapper around Core Data. Anyway, it could be less flexible. What type of app do you need to develop?
  • iOS-Coder
    iOS-Coder almost 11 years
    @flexaddicted I'm working on an existing app in which all 'table' data have previously been saved using streaming-objects (i.e. NSUSerDefaults, NSArray and the object NSCoder stuff). Since the new app-upgrade should involve 4 different (table)objects with 1:n, n:m, 1:n, 1:n relationships I really wanted to solve this using CoreData. The app must support iOS5.x and upwards, and using Xcode 4.6 on MountainLion caused a lot of compilation issues by adding CoreData. For this reason I found MagicalRecord which for the moment suits me well.