Reputation: 2535
I have searched quite a lot on the internet but can't find what I'm looking for.
I have this model where it could be a lot of users. So I have an entity called User
. The user has an NSSet
of records. And I want to fetch records from given user. I'm trying to do it like this but it still returns records from all users.
NSManagedObjectContext *context = _backgroundContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Record"
inManagedObjectContext:context];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date >= %@)",date];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"User = %@",currentUser];
NSPredicate *predicates = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:predicate,predicate1, nil]];
[fetchRequest setPredicate:predicates];
[fetchRequest setPredicate:predicate];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
I know it shouldn't be hard, but I can't find what it is, and I'm hoping some of you could help. Thanks in advance!
EDIT:
As I said I have an entity User
which has:
NSString name,
int age,
NSSet records, ...
Record
has its own properties such as:
NSDate date,
NSString name,
NSString event,
...
I want to form a fetch request to get records just from specific user. And I don't know how to do it, because I'm getting all of the records from every user.
records has a To-Many relationship. I can get records like currentUser.records, but i can't get user using record.User.
Upvotes: 0
Views: 1457
Reputation: 501
I'm assuming your model looks roughly like this, i.e. the records relationship has an inverse relationship called user:
It's importantant that this relationship is an inverse relationship because otherwise Core Data will not automatically maintain it. You can then query all Records for the given User on/after the given date like this:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Record"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"user = %@ AND (date >= %@)", currentUser, date];
NSError *error = nil;
NSArray *records = [_backgroundContext executeFetchRequest:fetchRequest error:&error];
NSLog(@"records: %@", records);
I've rewritten your code to be more compact, but the important change is that this will create the query in just one go.
Upvotes: 2
Reputation: 4398
As Martin R said, you're replacing your predicate. As he also mention, the user property should be lowercase, as I'm pretty sure that core-data enforces this. It should give you an error if you try creating a relationship with an upper case letter, so try
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"user = %@",currentUser];
instead. Obviously if your model doesn't define a property for user then that won't work either and you'll need to change it to whatever your model actually has, but that should work otherwise.
Edit:
Try adding an inverse relationship in your model. So your structure would look like :
user
NSString name,
int age,
NSSet records, ...
Record
NSDate date,
NSString name,
NSString event,
User user,
...
Then every time you create a new record, as well as adding the record to the users record set, set the user on the record object as well. This will make fetching the records a lot easier, and also it allows core data to keep data integrity:
"You should typically model relationships in both directions, and specify the inverse
relationships appropriately. Core Data uses this information to ensure the consistency of the
object graph if a change is made"
Once this is setup, you should easily be able to get the records user by simply calling record.user
If you need multiple users for multiple records, then simply setup the relationship as a to-many relationship, and change the User user
property to NSSet user
.
If you don't want to change your models this much, then I'm a bit confused with your question. You say you want to get the records for a given user? If so, then why don't you simply call user.records
as you have that relationship already defined? There's no need for an entire fetch request for that, let core data manage that one for you.
If you then want to filter the resulting Records based on the date, you can apply a predicate to the resulting array yourself, again without the need for a fetch request.
Upvotes: 1
Reputation: 539685
The error is here:
[fetchRequest setPredicate:predicates];
[fetchRequest setPredicate:predicate];
After setting the compound predicate, you overwrite it with the predicate for date
alone. You probably want to delete the second line.
EDIT: The fetch request requires that you have defined a inverse relationship user
from Record
to User
and use the exact name of this relationship in the predicate.
An alternative solution is to use the "forward" relationship from User
to Record
and filter the result:
NSSet *records = [currentUser.records filteredSetUsingPredicate:predicates];
or, if you prefer an array
NSArray *records = [[currentUser.records allObjects] filteredArrayUsingPredicate:predicates];
Upvotes: 1
Reputation: 2535
I have found what I've searched! I just needed to form a predicate using this
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF = %@",delegate.currentUser];
EDIT
Well it seems that i was wrong :/ That only seemed to work.
Upvotes: 0