Core Data NSFetchrequest integer - ios

I have the following scenario. I have an app that handles data by using Core Data. I have an entity called "Brothers" which has 3 attributes: Name, Status, Age.
lets say that I have 1 record on my database that has:
-Name ==> Joe (String)
-Status ==> Married (String)
-Age ==> 28 (Integer)
I have an UIlabel a UItextfield and a Button. I want to be able to type the name (in this case Joe) on the UItextfield press the button and display the age (in this case 28) in the UILabel. I would also like to store the age value into a variable type integer so I can make some calculations with it later on.
below the code that I have inside the button.
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"Brothers" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"age %d", [self.age.text integerValue]];
[request setPredicate:predicate];
NSError *error;
NSArray *integer = [context executeFetchRequest:request error:&error];
self.displayLabel.text = integer;
Update #1
I updated the code that i have inside the button and now i am able to search by the name and display the age. I'm still looking into storing the age as an integer into a variable so i can use it later on.
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"Brothers" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"firstname like %#", self.firstnameTextField.text];
[request setPredicate:predicate];
NSError *error;
NSArray *integer = [context executeFetchRequest:request error:&error];
if(integer.count <= 0){
self.displayLabel.text = #"No records found";
}
else {
NSString *age;
for (NSManagedObject *object in integer) {
age = [object valueForKey:#"age"];
}
self.displayLabel.text = [NSString stringWithFormat:#"age: %#",age];
}
}

A predicate is an expression. If the expression evaluates to true then the predicate is satisfied. So if you were searching by age you'd use e.g.
[NSPredicate predicateWithFormat:#"age = %d", [self.age.text integerValue]]
Or by name:
[NSPredicate predicateWithFormat:#"name = %#", someNameOrOther]
Or by both:
[NSPredicate predicateWithFormat:#"(name = %#) and (age = %d)", someNameOrOther, [self.age.text integerValue]]
A fetch request gets the actual NSManagedObjects. So you'd get back an array of Brothers. Therefore you probably want something more like this to output a name:
if([array count])
self.displayLabel.text = [array[0] name];
Or for an age:
...
self.displayLabel.text = [[array[0] age] stringValue];
Or whatever other property you're outputting.

I think your predicate is wrong, the proper format would be this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"age.integerValue == %d", [self.age.text integerValue]];

Related

NSPredicate weird crash with NSString

I'm trying to get a CoreData entity based on her name, to do that a created a method, that accepts a name parameter (NSString), so this is the method:
-(void)pegarCategoryByName:(NSString *)catName {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSLog(#"Category Name: %#", catName);
NSError *error = nil;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Categorias" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"categoria == '%#'", catName];
[fetchRequest setPredicate:predicate];
// [fetchRequest setFetchLimit:1];
NSArray *fetchedObjects = [[self managedObjectContext]executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects.count > 0) {
_categoriaAtual = [fetchedObjects objectAtIndex:0];
} else {
NSLog(#"Category not Found");
}
}
So lets say i call somewhere in my code:
[self pegarCategoryByName:#"Songs"];
When i run i get the NSLog: Category Name Songs, Category not Found and them the App crashes.
The weird part is, if i change the NSPredicate on pegarCategoryName to not use the NSString passed, here's and example:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"categoria == 'Songs'"];
Everything works just fine.
Do not enclose the %# placeholder in the predicate format in quotation marks:
[NSPredicate predicateWithFormat:#"categoria == %#", catName];
catName is already a string; you don't need to surround it with quotes, it would be the same as:
categoria == '#"Songs"'
so remove them:
#"categoria == %#"

Integer Comparison through Predicate

I am using core data in which I am having an entity called "Scan" who is having one attribute say electronic_id which is of NSNumber type. Now suppose in data base i am having 3 entries of this Scan attribute.
One entry of this entity having 35 as electronic_id.
Second entry of this entity having 354 as electronic_id.
Third entry of this entity having 375 as electronic_id.
I am performing searching on this attribute. so I when i start to search entity by passing 3 i want all these 3 objects.when i pass 35 then i want first two objects.
I want partial matches objects on NSNumber through predicate.
I am using this function.
-(void)filteredContentWithSearchText:(NSString*)searchText
{
if([searchText length])
{
int value=0;
value=[searchText intValue];
if ([strSelectedType isEqualToString:#"Electronic ID"])
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"electronic_id == %d",value];
NSManagedObjectContext *context =[self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Scan" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
NSError *error=nil;
NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
if (error==nil)
{
}
else if (error!=nil)
{
NSArray *results =[APP_DELEGATE CallForGetScan:YES Predicateis:predicate];
[arrSessionSearchData removeAllObjects];
[arrSessionSearchData addObjectsFromArray:results];
}
}
}
}
Please help how to compare integer in NSPredicate.
Thanks in Advance.
Try cast integer to string and compare it
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"electronic_id.stringValue CONTAINS[c] %#",searchText];
#sage444 your answer is what I have looking for hours. Works like a charm.
I just provide Swift version for future readers:
let predicate = NSPredicate(format: "%K.stringValue CONTAINS[c] %#",
#keyPath(YOUR_MODEL.number),
substring)

core data fetch request crash without error log

Contact entity has a many to one relationship to user, which has a userID field
Contact has a status string attribute that can be either 'approved', 'rejected', 'pending' etc
favorite boolean attributes
+ (NSSet *)fetchContactsWithUserID:(NSString *)userID approvedOnly:(BOOL)approvedOnly favoriateOnly:(BOOL)favoriateOnly {
NSString *predString = [NSString stringWithFormat:#"(user.userID = %#)", userID];
if (approvedOnly) {
predString = [predString stringByAppendingString:#" AND (status = approved)"];
}
if (favoriateOnly) {
predString = [predString stringByAppendingString:#" AND (favorite = YES)"];
}
NSPredicate *pred = [NSPredicate predicateWithFormat:predString];
return [self private_fetchEntitiesWithName:#"Contact" predicate:pred];
}
+ (NSSet *)private_fetchEntitiesWithName:(NSString *)name predicate:(NSPredicate *)predicate {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:name inManagedObjectContext:[self private_context]];
[fetchRequest setEntity:entity];
if (predicate) {
[fetchRequest setPredicate:predicate];
}
NSError *error;
NSArray *fetchedObjects = [[self private_context] executeFetchRequest:fetchRequest error:&error]; //CRASH ON THIS LINE!!!!!!
return [NSSet setWithArray:fetchedObjects];
}
stack trace:
There is no error logged out (i already enabled nszombie)
#"(status = approved)" is not a valid predicate. If approved is a string your predicate string should be #" AND (status = \"approved\")" or #" AND (status = 'approved')".
If you use a string literal directly in a predicate you have to enclose it in quotes.
Strings that are not enclosed in quotes are treated as keys by the NSFetchRequest.
This is done because you can actually check if two attributes are equal by using a predicate that compares those two, e.g.#"attribute1 = attribute2".
If you use a predicate format that contains %#, NSPredicate will automatically add quotes if the object you want to use as argument is a NSString.
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"foo = %#", #"Bar"];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"foo = Bar"];
NSLog(#"%#", p1);
NSLog(#"%#", p2);
yields:
xxx[4673:70b] foo == "Bar"
xxx[4673:70b] foo == Bar

Fetch objects from an entity of one to many relationship core data

I was scratching my head all the way through to get this problem solved my self but unfortunately i couldn't.
So my problem is i have multiple values corresponding to one lectures so i made lectureTpPbl,lectureToProfessor,lecturetoStudyProgram relation of type one to many relationship as shown in image.
i saved into the DB like below:
-(void)saveToDatabase:(NSMutableDictionary *)inData{
LectureDetails *lectureDetail = (LectureDetails *)[NSEntityDescription insertNewObjectForEntityForName:#"LectureDetails" inManagedObjectContext:context];
[lectureDetail setAverageRating:[inData valueForKey:kLectureAverageRating]];
[lectureDetail setCategoryID:[inData valueForKey:kLectureCategoryID]];
[lectureDetail setCategoryName:[inData valueForKey:kLectureCategoryName]];
[lectureDetail setLectureID:[inData valueForKey:kLectureID]];
[lectureDetail setSemesterID:[inData valueForKey:#"SemesterID"]];
[lectureDetail setStartTime:[inData valueForKey:kLectureStartTime]];
[lectureDetail setRatingType:[inData valueForKey:kRatingType]];
[lectureDetail setMonth:[NSNumber numberWithInt:[[[[inData valueForKey:kLectureDate] componentsSeparatedByString:#"-"] objectAtIndex:1] integerValue]]];
[lectureDetail setDateOnly:[NSNumber numberWithInt:[[[[inData valueForKey:kLectureDate] componentsSeparatedByString:#"-"] objectAtIndex:2] integerValue]]];
for (id prof in [inData valueForKey:#"Professors"]) {
ProfessorsInLecture *profData = (ProfessorsInLecture *)[NSEntityDescription insertNewObjectForEntityForName:#"ProfessorsInLecture" inManagedObjectContext:context];
profData.professorID=[NSNumber numberWithInt:[[prof valueForKey:#"ProfessorID"]integerValue]] ;
profData.professorFirstName=[prof valueForKey:#"ProfessorFirstName"];
profData.professorLastName=[prof valueForKey:#"ProfessorLastName"];
profData.ProfessorUserName=[prof valueForKey:#"ProfessorUserName"];
[lectureDetail addLectureToProfessorObject:profData];
}
for (id prog in [inData valueForKey:#"StudyPrograms"]) {
StudyProgramInLecture *stdyProgramData = (StudyProgramInLecture *)[NSEntityDescription insertNewObjectForEntityForName:#"StudyProgramInLecture" inManagedObjectContext:context];
stdyProgramData.sMID=[prog valueForKey:#"SMID"];
[lectureDetail addLectureToStudyProgramObject:stdyProgramData];
}
for (id pblData in [inData valueForKey:#"PBLs"]) {
PBLinLectures *pbl = (PBLinLectures *)[NSEntityDescription insertNewObjectForEntityForName:#"PBLinLectures" inManagedObjectContext:context];
[pbl setLecturePBLID:[pblData valueForKey:#"LecturePBLID"]];
[pbl setPBLID:[pblData valueForKey:#"PBLID"]];
[lectureDetail addLectureToPBLObject:pbl];
}
NSError *error1;
if (![context save:&error1])
{
//NSLog(#"ERROR--%#",error);
abort();
}
}
all the data is getting save correctly but i am getting problem in fetching the data.
Now suppose i have to fetch a lecture whose semesterID=7 and month=12 and day=20 and (in relation table)sMID=2 and (in relation table)pBLID=4.
what i have done so far is to fetch is
-(NSMutableArray *)fetchDataforMonth:(NSNumber *)month andDate:(NSNumber *)dateOnly
{
NSEntityDescription *entity = [NSEntityDescription entityForName:#"LectureDetails" inManagedObjectContext:context];
// Setup the fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY lectureToPBL.pBLID ==%#", [NSNumber numberWithInt:[[[UserDetail sharedInstance].userDetail valueForKey:#"pBLID"]integerValue]]];
NSPredicate *pred1 =
[NSPredicate predicateWithFormat:#"(dateOnly == %#)",dateOnly];
NSPredicate *pred2 =
[NSPredicate predicateWithFormat:#"(month == %#)",month];
NSPredicate *pred3 =
[NSPredicate predicateWithFormat:#"(semesterID == %#)",[NSNumber numberWithInt:[[[UserDetail sharedInstance].userDetail valueForKey:#"semesterID"]integerValue]]];
NSPredicate *pred4 = [NSPredicate predicateWithFormat:#"ANY lectureToStudyProgram.sMID ==%#", [NSNumber numberWithInt:[[[UserDetail sharedInstance].userDetail valueForKey:#"programID"]integerValue]]];
NSArray *compPredicatesList = [NSArray arrayWithObjects:pred1,pred2,pred3,predicate,pred4, nil];
NSPredicate *CompPrediWithAnd = [NSCompoundPredicate andPredicateWithSubpredicates:compPredicatesList];
[request setPredicate: CompPrediWithAnd];
// Fetch the records and handle an error
NSError *error;
NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];
return mutableFetchResults;
}
If there is one sMID and one pBLID then fetching is working fine otherwise i am not getting an object in fetch result.
Suppose i have a lecture whose semesterID is 7 and month=12 and day=20 and have multiples sMID such as 1,2,3 and multiples pBLID such as =4,5,6
and i want to fetch a lecture whose month=12 and day=20 and sMID=2 and pBLID=4
Can anybody tell me how to do that?
Any Help will be appreciated.
Thanks
First filter the Lecturers whose month=12 and day=20 from LectureDetails entity:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(month == %#) AND (dateOnly == %#) ",month, dateOnly];
[request setPredicate: pred];
NSError *error;
NSArray *lectureList = [context executeFetchRequest:request error:&error];
then filter this array with pBLID and sMID.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(ANY lectureToStudyProgram.sMID ==%#) AND (ANY lectureToStudyPBL.pBLID ==%#)", sMID, pBLID];
lectureList = [lectureList filteredArrayUsingPredicate:predicate];
Now lectureList will give you the result.

Set 2 NSPredicates on a NSFetchRequest

I'm using Core Data and have a to-many relationship with the following entities:
Athlete(evals)<-->>Eval(whosEval)
It starts with a table view that lists ALL athletes in the database. Then when you select an Athlete it pulls up their Evals in a table view. The problem is the way I am doing this is through checking their full name. Unfortunately, it is possible for 2 athletes to have the same name. For this reason, I check their parent's name as well, but I think I am doing it incorrectly. Can anyone explain why the following doesn't work and how I should do it correctly? What happens with this code is if 2 Athletes have the same name, they'll share results. Even if their Parent's Name is different.
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSFetchRequest *athleteRequest = [[NSFetchRequest alloc] init];
[athleteRequest setEntity:[NSEntityDescription entityForName:#"Athlete" inManagedObjectContext:_managedObjectContext]];
NSError *athleteError = nil;
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"full == %#", _athletesFullName];
[athleteRequest setPredicate:athletePredicate];
NSArray *results = [_managedObjectContext executeFetchRequest:athleteRequest error:&athleteError];
if([results count] >1){
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"pfull == %#", _athletesParentsFullName];
[athleteRequest setPredicate:athletePredicate];
}
Athlete *athleteSelected;
if([results count] >0){
Athlete *currentAthlete = [results objectAtIndex:0];
athleteSelected = currentAthlete;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosEval == %#", athleteSelected];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Eval" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
Modifying athleteRequest after the request has been executed does not have
any effect on the result. Why not simply
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"full == %# AND (pfull == nil OR pfull == %#)",
_athletesFullName, _athletesParentsFullName];
?
Apart from that, it would probably be better to identify the objects by some
unique identifier (e.g. a unique athlete number) instead of relying on name
and parent's name.
Your scenario is really simple, but for more complex situations, you can use compound predicates.
Read this awesome article from NSHipster for more informations:
http://nshipster.com/nspredicate/

Resources