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?
Use autorelease before adding objects to a collection?
What methods do I have to implement in order to re-arrange the UITableView rows?
Loading a Singleton's state from NSKeyedArchiver
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.
How to reload a uiviewcontroller on the iPhone
(The specific syntax will depend on the inverse relationship name, and whether that inverse is a to-one or to-many.).
Multiple UILabels to display decorated XML markup
Round NSDate to the nearest 5 minutes
How to release memory associated by CGImageCreateWithImageInRect
Has anyone implemented the PayPal API through a native iPhone app?
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..
where relationship_to_a is name of the relationship to A in your B managed object.. Hope this helps.. Btw.: To all those other answers that suggests to use the faults from the relationship set: I have tried this myself, and it was way slower than fetching them, because Core Data apparently fire the faults one after another (not in batch), therefore making it painfully slow for larger sets.. Actually, if you get your A instance by fetching, then you can try to set relationshipKeyPathsForPrefetching in your NSFetchRequest to YES, and then all the objects in the relationship shouldn't be faults.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *BEntity = [NSEntityDescription entityForName:@"B" inManagedObjectContext:moc]; [fetchRequest setEntity:BEntity]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(relationship_to_a = %@)", [yourAInstance objectID]]; [fetchRequest setPredicate:predicate];
But this didn't work for me, so I stuck with the 'fetch solution'..
Now, one way of doing this is to build a predicate like the one below and apply it to entity B:.
But this is a terribly slow way of doing things and should be avoided at all costs.
NSPredicate *Predicate = [NSPredicate predicateWithFormat: @"ANY hasParent.label == 'A'"];
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..
This is very fast.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES]; NSArray *lotsOfB = [[[A hasRelationsTo] allObjects] sortedArrayUsingDescriptors: sortDescriptors];
No lag in the simulator or on the device.
But you cannot use a NSFetchedResultsController sad times :-(. Hope that helps..
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...