The Core Data Documentation states that:
The fetch request associated with the [fetched] property can have a sort ordering, and thus the fetched prope
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!
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.
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.
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"];
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;
}
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.