Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data: sorting by count in a to-many relationship

I am currently trying to setup a NSFetchedResultsController that will order my table view based on the number of entities in a to-many relationship. I am not sure if this makes a difference when counting, but this is also an inverse relationship.

I thought something like this would work just fine:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Parent"
inManagedObjectContext:managedObjectContext];

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] 
initWithKey:@"children.@count" ascending:YES];

NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1,
nil];

[fetchRequest setSortDescriptors:sortDescriptors];

I keep getting 'Keypath containing KVC aggregate where there shouldn't be one; failed to handle children.@count'.

Any ideas on what could be going wrong?

like image 261
avenged Avatar asked Oct 10 '10 03:10

avenged


3 Answers

I added the KVO accessor -countOf<Key> as an attribute to my managed object model as an integer type. I did NOT implement anything for this attribute in my NSManagedObject subclass, as all the magic seems to happen under the hood.

So in this particular case, add an attribute countOfChildren to the Parent entity. This should remove the exception.

EDIT: This fix seems to only work on iOS 6.1, not on iOS 6.0.

like image 145
Bram De Geyter Avatar answered Oct 23 '22 10:10

Bram De Geyter


Since iOS 13 (and friends) you can create a derived attribute called childCount with the derivation expression children.@count and then set fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"childCount" ascending:NO]]

like image 43
numist Avatar answered Oct 23 '22 12:10

numist


AS far as I know you can't apply the @count in the query, but you can easily apply it to the fetched array.

NSEntityDescription * entity = [NSEntityDescription entityForName:@"Parent" inManagedObjectContext:self.managedObjectContext];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
NSError *error;
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"children.@count" ascending:NO];
NSArray *descriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSArray *sortedArray  = [results sortedArrayUsingDescriptors:descriptors];
like image 24
jacob bullock Avatar answered Oct 23 '22 11:10

jacob bullock