views:

44

answers:

2

I have two entities. Client and Project. A Client has many Projects, but a Project can only be assigned to one Client. This has been designed with the datamodel.

  • Client entity has attribute clientName and relationship to-many projects
  • Project entity has attribute projectName and relationship to-one client

I want to retrieve all Clients from my ManagedObjectContext where the Clients are sorted by clientName ascending and then have the Projects for that Client by projectName ascending.

This is my current code, where I KNOW it is wrong since there is no way for Client entity to sort by the projectName:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Client" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];

// Creating the sort descriptors array.
NSSortDescriptor *clientSort = [[NSSortDescriptor alloc] initWithKey:@"clientName" ascending:YES];
// this next row is super wrong
NSSortDescriptor *projectSort = [[NSSortDescriptor alloc] initWithKey:@"projectName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSort. projectSort, nil];
[fetchRequest setSortDescriptors:sortDescriptors];  

NSError *error;
// Assign to NSArray of ViewController
clientArray = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];

After this has been assigned to clientArray, I want to go to another method and ask for the Projects and have them in ascending order. Example:

Client *temp = (Client *)[clientArray objectAtIndex:selectedClient];        
NSArray *projectsArray = [temp.projects allObjects];
Project *project = [projectsArray objectAtIndex:selectedProject];       
return project.projectName;

I saw an implementation where they got the Clients and then sorted the projects manually... But this is kind of expensive and I'm hoping there are functions to do this when the Context gets queried.

A: 

Try using a key path for the sort, such as project.projectName in the sort descriptor. This is a bit of a shot in the dark because I haven't tried this myself so don't kill me if I'm wrong.

Nimrod
I thought about this, but the relationship returns an NSSet on `projects`, so that doesn't have a `projectName` attribute. Unless it is internally done, which I don't think it would be designed like that.
elcool
A: 

You could add your own custom property to Client

@interface Client : NSManagedObject {
}

// ... other properties
@property (nonatomic,readonly) NSArray* orderedProjects;

@end

@implementation

// ... @dynamic etc

@dynamic orderedProjects;

- (NSArray*)orderedProjects {
    NSArray* sort = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"projectName" ascending:YES]]
    return [[self.projects allObjects] sortedArrayUsingDescriptors:sort];
}

@end

Now you just have to fetch all clients, which now each have sorted projects. Performance wise I'm not sure this is the best approach but it makes for cleaner code I think.

aegzorz
Yes, this is what I originally thought, but I'm looking for a way to do it when calling the FetchRequest.
elcool