Help me to get the result based on condition - iphone

I have created a Users class based on NSManagedObject with following attributes (id,name,age etc).
I am using the core data model but i am not sure how to do the follwing...
Now i would like to know How can i get the user detail based on user id.
example: select * from users where id = 1
please help me out.

You should use NSPredicate class for executing SQL commands. The code:
NSManagedObjectContext *context = self.managedObjectContext; // specify your MOC object
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"users" inManagedObjectContext:context]; // specify your entity (table)
NSPredicate *predicate = [NSPredicate predicatewithFormat:#"id == %d",yourID]; // specify your condition (predicate)
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *array = [context executeFetchRequest:fetchRequest error:&error]; // execute
[entity release];
[predicate release];
[fetchRequest release];
if (array == nil) {
// Error: no objects returned
} else {
// Success: do whatever you want
}
Step 1: Alloc/init NSFetchRequest
You need to alloc/init a NSFetchRequest object if you want to execute queries.
Step 2: Select entity
If you want to specify select * from users ..., you should use NSEntityDescription:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"users" inManagedObjectContext:context];
At the end you need to 'attach' your entity description to your NSFetchRequest object via:
[fetchRequest setEntity:entity];
Step 3: Condition
If you want to have a condition (e.g. ... where id = 1), you have to implement NSPredicate.
NSPredicate *predicate = [NSPredicate predicatewithFormat:#"id == %d",yourID];
yourID must be a number (e.g. 1, 2, 7 or 46).
And, again:
[fetchRequest setPredicate:predicate];
Step 4: Let's execute it!
NSArray *array = [context executeFetchRequest:fetchRequest error:&error];
All the records that meet the conditions will be returned as array of NSManagedObjects.
Step 5: Release objects
[entity release];
[predicate release];
[fetchRequest release];
Step 6: Do something
If there are no objects that meet the conditions, array object will be nil. You can check it and deal with the error via:
if (array == nil)
Check out Core Data Programming Guide for more info. :)

Related

NSFetchRequest for all children of a parent

How do I fetch all child entities of a parent?
I have a table populated by a parent entity in Core Data. When the user touches a cell I intend to show another table with all children of that parent.
How does the NSFetchRequest look like for this please?
Edit:
model is like this:
student>>dates [one to many, one student have many days]
So I want all dates for any given student (selected by touching in student table cell for that student), then populate dates table with dates for that student.
Thanks!
Assuming that the entity and the class names are Student and Date, and the reverse relationship for Date->Student is called student,
Student *aStudent = ...;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity: [NSEntityDescription entityForName: #"Date" inManagedObjectContext: [aStudent managedObjectContext]]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: #"student == %#", aStudent]];
You don't need a separate fetch request for this. All of the objects from the to-many relationship (don't call them child entities, that is misleading and incorrect) are available by accessing the relationship from the student object - something like student.dates. This gives you an NSSet, you can sort it and turn it to an array if you need to.
Within your first table delegate, when you touch a specific cell, I'll inject the specific parent property to the second table controller. For example:
SecondController secondController = ... // alloc-init
secondController.studentToGrab = ...
where SecondController declaration has a studentToGrab property like the following:
#property (nonatomic, retain) Student* studentToGrab; // use strong with ARC, if non-ARC remember to release it
and in definition synthesize it.
Then in your second controller, within viewDidLoad method you could do:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"YourNameEntityForDate" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"student == %#", studentToGrab];
[fetchRequest setPredicate:predicate];
// you can also use a sortdescriptors to order dates...
NSError *error = nil;
NSArray *resultArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error != nil) {
NSLog(#"Error: %#", [error localizedDescription]);
abort();
}
// use resultArray to populate something...
A remark when you deal with table you could also use NSFetchedResultController class. It has advantages when used for displaying data in tables.
If you have custom classes, you could traverse the generated relationship (return [student dates]). That will get you an unordered NSSet on iOS4, or, you can do it with a fetch request (note I use ARC so no releases/autoreleases here):
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Date"
inManagedObjectContext:moc];
[fetchRequest setEntity:entity];
NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:3];
[predicates addObject:[NSPredicate predicateWithFormat:#"student == %#", aStudent]];
// You might add other predicates
[fetchRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:predicates]];
// and if you want sorted results (why not, get the database to do it for you)
// sort by date to the top
NSArray *sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"dateAdded" ascending:NO]];
}
[fetchRequest setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSArray *sorted = [moc executeFetchRequest:fetchRequest error:&error];
if (error) {
// Handle the error, do something useful
}
return sorted;

Quick Question About NSFetchRequest and Relationship

In my Core Data model, I have an entity Session and Exercise.
Session has a to many relationship to Exercise (there is a one-one inverse relationship as well).
In my fetch, I am trying to find all Session object that are related to the current Exercise.
I am using the following code which isn't working.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat: #"exercise = %#", exercise.name]];
NSEntityDescription *sessionEntity = [NSEntityDescription entityForName:#"Session" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:sessionEntity];
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(#"Fetch error: %#", error);
self.sessionArray = results;
Here is my data model:
First, from the screenshot it seems that your relationship attribute of the Session entity is called exercises not exercise.
Also, it seems to me that it would work if you searched not the Session entity but the Exercise entity and then iterate through the resulting array to extract the sessions.
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:"name == %#", exerciseName]];
NSEntityDescription *exerciseEntity = [NSEntityDescription entityForName:#"Exercise" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:exerciseEntity];
...
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
...
NSMutableArray *mutableSessionArray = [NSMutableArray array];
for (Exercise *ex in results) {
Session *session = [ex exercises];
if (session) [mutableSessionArray addObject:session];
}
self.sessionArray = [NSArray arrayWithArray:mutableSessionArray];
The relationship of the Exercise entity called exercises could be called session for clarity. I would recommend renaming it.
BTW, you can also write = instead of ==, they are equivalent, as far as I know. In the Predicate Programming Guide section on Predicate Format String Syntax it says:
=, ==
The left-hand expression is equal to the right-hand expression.
In your predicate you use =, == is the comparison operator. I think that's where you're going wrong.
Source: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/Reference/NSPredicate.html

Using NSPredicate to get an array of Core Data objects?

Say I have a Core Data entity called Person. How would I get an NSArray of Persons whose properties match certain values? For instance someone of a particular age, height, or weight... or someone with a whose height,weight and age are specific values...
Can I use an NSPredicate like so:
NSPredicate *pred =
[NSPredicate predicateWithFormat:
#"(age == 25) OR (height_in_cms == 185) OR (age == 30 AND height_in_cms == 170 AND weight_in_kgs == 80)";
// All properties are NSNumber
I'm not an expert on the syntax for predicateWithFormat:, but you have the basic gist. You can find details on the format in Apple's Predicate Programming Guide. If you're asking what to do with the predicate once you have it, here is a snippet that shows you the steps:
// Create a fetch request.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Set the entity for the fetch request.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"EntityName" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[entity release];
// Set the predicate for the fetch request.
[fetchRequest setPredicate:predicate];
// Perform the fetch.
NSError *error;
NSArray *array = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
If you want the results to be sorted, you can pass an array of sort descriptors to the fetch request using setSortDescriptors: prior to executing the fetch.
You can follow the given statement if you have these value in a variable.
[fetchResults filterUsingPredicate:[NSPredicate predicateWithFormat:#"age == %i OR hieght== %i AND weight==%i",age,height,weight]];
And also your approach is correct in case for specific values but your statement having syntax error so maintain proper syntax

How to determine number of objects in one-to-many relationship in CoreData

So, I've got a one-to-many relationship of Companies to Employees in CoreData (using a SQLite backend on iOS, if that's relevant). I want to create a predicate that only returns Companies that have 0 Employees associated with them. I could do it by getting all the Companies and iterating over them, but that would be (I assume) much slower.
Any ideas?
Thanks,
-Aaron
After trying #falconcreek's answer and getting an error (described in my comment on his answer), I did some googling and determined that the answer was
NSPredicate *noEmployeesPredicate = [NSPredicate predicateWithFormat:#"employees.#count == 0"];
Now everything works über efficiently. Thanks!
Assuming your Company -> Employee relationship is named "employees"
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Company" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
// the following doesn't work
// NSPredicate *noEmployeesPredicate = [NSPredicate predicateWithFormat:#"employees = nil OR employees[SIZE] = 0"];
// use #count instead
NSPredicate *noEmployeesPredicate = [NSPredicate predicateWithFormat:#"employees = nil OR employees.#count == 0"];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (error)
{
// Deal with error...
}

Core Data: Returning properties depending on a value

can anyone guide me how to create a fetch request that will query an entity and returns any properties that qualify my criteria.
Here's what I have. I have an entity that has 35 properties, all are in types of float.
What I need was to see all properties of the entity which values was <= zero.
I know how to return the values of the properties but not how to return the name of the property.
Thanks,
CoreData doesn't return properties. It returns entities, which then have properties. In any case, you'd have to do something like this:
(The following is pseudo-code done from memory. Treat it accordingly.)
NSString *query = #"(property1 <= 0) && (property2 <= 0)";
NSPredicate *predicate = [NSPredicate predicateWithFormat:query];
NSEntityDescription *entity = [NSEntityDescription entityDescriptionForName:#"Entity" inManagedObjectContext:context];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
[fetch setEntity:entity];
[fetch setPredicate:predicate];
NSError *error = nil;
NSArray *entities = [context executeFetchRequest:fetch error:&error];
// Let's just assume we got one
NSManagedObject *obj = [entities objectAtIndex:0];
float value = [obj valueForKey:#"property1"];
Or something like that.