Core Data: Predicate that Returns Objects of Another Entity
I开发者_运维百科 have two entities in my data model: Details
and Lookup
. I need find all Details
objects related to a specific Lookup
object that has specific attribute value and then return those Details
objects via a fetched results controller.
My NSManagedObjectSubclasses:
@interface Details : NSManagedObject {
@privateI
}
@property (nonatomic, retain) NSString * owner;
@property (nonatomic, retain) NSString * introduction;
@property (nonatomic, retain) NSString * id;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSString * created;
@property (nonatomic, retain) NSString * modified;
@property (nonatomic, retain) NSNumber * type;
@property (nonatomic, retain) NSString * desc;
@interface Lookup : NSManagedObject {
@private
}
@property (nonatomic, retain) NSDate * search_date;
@property (nonatomic, retain) NSString * search_phrase;
@property (nonatomic, retain) NSSet* searchResults;
I need to find a Lookup
object based on its search_phrase
attribute and then get all the related Details
objects and return those in a fetched results controller.
I think I have to search for the Lookup
object first, then walk the NSSet of Detail objects but I do not know how to return those in the NSFetchedResultsController.
I've tried:
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"search_phrase = %@", self.searchPhrase];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.predicate = predicate;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Lookup" inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"search_phrase" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:nil cacheName:@"Searches"];
I have a request that finds the right Lookup
object but I don't know how to get the related Detail
objects from the fetched results controller.
Firstly, you don't have a reciprocal relationship defined between Details
and Lookup
but just a one-way Lookup
to Details
. You need to add a relationship to both the data model entity running from Detail
to Lookup
and have it set has the recipocal of Lookup.searchResults
and your Detail
class needs a property something like:
@property (nonAtomic,retain) Lookup *lookup;
Having a reciprocal relationship lets you find Detail
objects by starting with a Lookup
object and lets you find a Lookup
object starting with a Detail
object.
If you want you tableview to display a list of Detail
objects, then you need to configure the fetched results controller's fetch request to fetch against the Detail
entity. As a rule of thumb, you always set the fetch request entity to the entity whose objects you wish to display in the tableview.
The predicate likewise will be run against the Detail
entity so you need a predicate that evaluates against a keypath that starts with a property of the Detail
entity. In this case, we want all Details
objects whose related Lookup
object has a search_phase
attribute equalling a provide value. So:
NSPredicate *p=[NSPredicate predicateWithFormat:@"lookup.search_phrase==%@", self.searchPhrase];
Now setup your fetch request thusly:
NSFetchRequest *fetch=[[NSFetchRequest alloc] init];
NSEntityDescription *detailsEntity=[NSEntityDescription entityForName:@"Details" inManagedObjectContext:self.context];
[fetch setEntity:detailsEntity];
[fetch setPredicate:p];
//.. set up a sort however you want the details to appear in the tableview
Give this fetch to your NSFetchedResultsController and it will return the Detail
objects you are looking for.
In summary:
- Always use reciprocal relationships in a data model so you can have flexibility.
- When using a fetched results controller, set the entity of the fetch request to the entity whose objects you wish to appear in the tableview.
Hard to answer without some of your sample code or even the actual relationships, but here goes:
- Perform your initial filter on table A. This gives you a set of results containing a number of objects.
- Query table B with your filter and
AND #Put name of the relationship here# IN (the results of 1)
Something else to add though, you should stop thinking about core data as a relational database. It's an object graph. Core data may or may not use different tables to store the data. What you should be concerned with are the objects and their relationships.
If I understand correctly you don't really want a 1 to many, but a many to many. You will then be able to perform both queries at once with a query for B objects:
A.your.a.query == 'What you're querying for' AND your.b.query == here
精彩评论