SpaceDog SpaceDog - 4 months ago 11
iOS Question

How to pull a sorted list from Core Data when the entity has a relation to another entity

I have two entities:

Product
and
Category
. They are defined like this:

PRODUCT

name = string

code = string

fromCategory = relation to category,
toOne


CATEGORY

category = string

toProduct = relation to product,
toMany


So one product can only belong to one category and a category can be assigned to many products.

This is the problem. I have products like this:


  • laser ship (toy)

  • doll (toy)

  • red mercedes (car)

  • robot (sci-fi)

  • peach (fruit)

  • apple (fruit)

  • aston martin (toy)

  • mouse (computer)



If I pull a list from core data sorted by the name I get this


  • apple (fruit)

  • aston martin (toy)

  • doll (toy)

  • laser ship (toy)

  • mouse (computer)

  • peach (fruit)

  • red mercedes (car)

  • robot (sci-fi)



but what I want is this:


  • mouse (computer)

  • red mercedes (computer)

  • apple (fruit)

  • peach (fruit)

  • robot (sci-fi)

  • aston martin (toy)

  • doll (toy)

  • laser ship (toy)



In other words, I want it primarily sorted by the category and then by the name, cause I want related items to be together on the table view.

This is the code I have to pull it sorted by the product's name:

@interface NSObject (ProductsBundlesExtensions)

+(NSArray *)sortDescriptorArrayByKey:(NSString *)key;

@end


@implementation NSObject (ProductsBundlesExtensions)



+(NSArray *)sortDescriptorArrayByKey:(NSString *)key {
return @[[NSSortDescriptor sortDescriptorWithKey:key
ascending:YES
selector:@selector(localizedStandardCompare:)]];
}

@end


+ (NSArray*)allSortedItemsInContext:(NSManagedObjectContext *)context
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];

request.entity = [NSEntityDescription entityForName:NSStringFromClass([self class])
inManagedObjectContext:context];

// sorting by product's name
[request setSortDescriptors:[NSObject sortDescriptorArrayByKey:@"name"]];

NSError *error;
NSArray *all = [context executeFetchRequest:request error:&error];

return all;
}


This is my problem: how do I do a sort by the category if that is an entity relation? What
NSSortDescriptor
will do that? Sort by the relation and then by the name?

Answer

Just use two sort descriptors (the NSObject category is too restricted to be used)

[request setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"fromCategory.category"] 
                                                           ascending:YES 
                                                            selector:@selector(localizedStandardCompare:),
                             [NSSortDescriptor sortDescriptorWithKey:@"name"] 
                                                           ascending:YES 
                                                            selector:@selector(localizedStandardCompare:)]];

You could extend the category to consider multiple keys

+ (NSArray *)sortDescriptorArrayByKeys:(NSArray<NSString *> *)keys {
  NSMutableArray *descriptors = [NSMutableArray array];
  for (NSString *key in keys) {
    [descriptors addObject:[NSSortDescriptor sortDescriptorWithKey:key
                                                         ascending:YES
                                                          selector:@selector(localizedStandardCompare:)]];
  }
  return [descriptors copy];
}

Then you can write

[request setSortDescriptors:[NSObject sortDescriptorArrayByKeys:@[@"fromCategory.category", @"name"]]];
Comments