views:

2031

answers:

4

I want to fetch objects B which has a to-many relationship with object A (ie. A -->> B). I already have A in memory. I know I could get a NSSet of the B objects from A, but would it be better to make a fetch request of the B objects (especially if I want to sort sections by date in a UITableView)?

How would I make such a request that only gets the B objects belonging to a single object A?

+3  A: 

You must specify a reverse relationship in Class B in order to do what you are asking.

However, I'm not sure why you are objecting (no pun intended) to grabbing the set of B objects already in object A. Even though the objects themselves are lazy loaded, since you already have A in memory, I have a hunch (although an expert would need to verify) that it would be more efficient to simply grab the set from A than to specify a new NSPredicate, and create a completely new Fetch.

Of course, by "more efficient" we're talking milliseconds, even on a device as slow as the iPhone. I'd grab the set from object A because the syntax is cleaner. The fact that it may also be faster is a bonus.

mmc
I would asked this question because I want the B objects to be sorted by date. And I though it might be faster and less cpu intensive to have the core data database presort a large set (potentially 200+) of objects instead of using code.
Devin: if you wanted the B objects sorted, you should add that to the original question. I'd like to know the answer too!
Adam Douglass
I'm interested in this too: http://stackoverflow.com/questions/4003659/is-it-possible-to-have-core-data-sort-the-many-part-of-a-to-many-relationship-d. I know you can batch force a fault. I wonder if you can sort it when you do?
JoBu1324
+3  A: 

If you are already holding an instance of A, just access the related B instances through A's accessor.

If you need to directly fetch all the B's related to a particular A (you don't in this case), you'd build a fetch request for the B entity, with a predicate based on the (inverse) relationship of Bs to A. (The specific syntax will depend on the inverse relationship name, and whether that inverse is a to-one or to-many.)

Jim Correia
A: 

I am in a similar situation.

I want to use a NSFetchedResultsController to manage B's in the one to many (A-->>B) relationship. Now, one way of doing this is to build a predicate like the one below and apply it to entity B:

NSPredicate *Predicate = [NSPredicate predicateWithFormat:
              @"ANY hasParent.label == 'A'"];

But this is a terribly slow way of doing things and should be avoided at all costs. I tried this on 25,000 objects to retrieve about 300 and it took the simulator about 15 seconds. It wouldn't finish the fetch on the iPhone and crashed repeatedly.

The other way would be to do what has already been mentioned, create an NSArray from the set held by A and sort it. If you send allObjects to a set you get an array back. A is an NSManagedObject fetched before.

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
                                   initWithKey:@"Name"
                                   ascending:YES];

NSArray *lotsOfB = [[[A hasRelationsTo]
                   allObjects]
                   sortedArrayUsingDescriptors: sortDescriptors];

This is very fast. No lag in the simulator or on the device. But you cannot use a NSFetchedResultsController sad times :-(

Hope that helps.

pingbat
A: 

I am also in a similar situation.

I didn't have as much objects like pingbat does, but it took 15 sec to fetch with "ANY hasParent.label == 'A'"

I do need to use NSFetchedREsultsController, hence I have to re-architecture the model. What I did was to to store the to-many relationship as a string property and construct the predicate "hasParent contains %@".

The lesson I learnt is that having a predicate that transverse a to-many relationship has a BIG performance hit..

samwize