NSPredicate for simple fetchRequest - ios

I am using Core Data to save previous searches in a SearchBar. My entity is very simple, it just has the property:
previousSearch (NSString)
When the user types in the search bar, I want to search the database for my previous search. I keep getting 0 results though.
Here is the code that retrieves the data from Core Data.
- (void)filterContentForSearchText:(NSString *)searchText {
[self.filteredLastSearches removeAllObjects];
NSEntityDescription *search = [NSEntityDescription entityForName:#"Search" inManagedObjectContext:_managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:search];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"previousSearch=[c]%#", searchText];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *fetchedObjects = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(#"Error filtering search: %#", [error description]);
}
_filteredLastSearches = [NSMutableArray arrayWithArray:fetchedObjects];
}
fetchedObjects is always empty and I'm not sure why. I can see in the database that the db actually has the ZPREVIOUSSEARCH with a couple values that I've tried to show while searching, but it's always empty. Is there something I'm missing? Thanks in advance.

I'm not sure if = operator work with [c]. Try to use like instead:
[NSPredicate predicateWithFormat:#"previousSearch like[c] %#", searchText];
Also you may want to search not equal results but results that contains (or begins with) your text. In this case you may use contains or beginswith.
[NSPredicate predicateWithFormat:#"previousSearch contains[c] %#", searchText];
[NSPredicate predicateWithFormat:#"previousSearch beginswith[c] %#", searchText];

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)

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.

NSPredicate multiple ANY query with CoreData

I'm trying to find all instances of an object that contain a reference to a combination of separate objects in my object graph.
recommendation
may contain one or more of the following three objects:
damageType
areaDamaged
validVehicles
This structure is built from an import of an existing system's file format and I am unable to restructure the object graph.
I'm using an NSPredicate to find all recommendation objects that have a damageType matching a selected damage as follows:
NSFetchRequest *fetchRequestDamages = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Recommendation class])];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY damageType == %#", _currentRecordedDamage.damageType];
But want the filter to return all Recommendations that have matches for a specific damageType, areaDamaged and validVehicle
I've tried
NSMutableArray *predicates = [[NSMutableArray alloc] initWithCapacity:2];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY damageType == %#", _currentRecordedDamage.damageType];
[predicates addObject:predicate];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"ANY areaDamaged == %#", _currentAreaDamaged];
[predicates addObject:predicate2];
NSPredicate *predicate3 = [NSPredicate predicateWithFormat:#"ANY validVehicles == %#", _currentVehicle];
[predicates addObject:predicate3];
fetchRequestDamages.predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
fetchRequestDamages.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequestDamages managedObjectContext:[RKManagedObjectStore defaultStore].mainQueueManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController.delegate = self;
NSError *error;
[self.fetchedResultsController performFetch:&error];
int resultsFound = self.fetchedResultsController.fetchedObjects.count;
but it seems this returns the set of all objects satisfying any of the predicates - I'd like the set of objects that match all three.
I'm looking into using SUBQUERY but can't quite make sense of how to create this query?
Just combine the three predicates with "AND" to find the objects that match all of them:
NSArray *predicates = ... // your array of predicates
NSPredicate *finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
[fetchRequestDamages setPredicate:finalPredicate];
Why not to use AND in one query?
Something like:
damage = %# AND damagePoints = %# AND damageCost = %#
and:
damageType IN %#
Where %# in the last code example should be an array/set or something else.

Core Data: deleteObject crashes application, NSPredicate the cause?

I'm using a UICollectionView along with Core Data.
I can't seem to figure out why I can't remove an object from Core Data. It crashes at [self.managedObjectContext deleteObject:animation]; with an index 0 beyond bounds for empty array error. The following method is a delegate method that gets invoked from another viewcontroller. It gets a timestamp NSInteger and should create an NSPredicate with that timestamp.
The strange thing is that when I take the animationTimestamp NSInteger and hardcode it like:
[NSPredicate predicateWithFormat:#"timestamp == %i", #"1370169109"] it works and the object gets deleted without the error. However, when I want to pass the parameter as the argument it crashes. I've tried making it a string, NSNumber etc. Nothing works when I take the parameter, it only does when I hardcode it. I've logged animationTimestamp and it shows the correct value, so I'm stuck.
Thanks!
- (void)deleteAnimationWithTimestamp:(NSInteger)animationTimestamp {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Animations" inManagedObjectContext:self.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"timestamp == %i", animationTimestamp];
[fetchRequest setPredicate:predicate];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *animations = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *animation in animations) {
[self.managedObjectContext deleteObject:animation];
}
// Save core data
if (![self.managedObjectContext save:&error]) {
NSLog(#"Couldn't save: %#", [error localizedDescription]);
}
[self.animationsCollectionView reloadData];
}
EDIT:
More info that might matter. The timestamp attribute in the model is a 64 bit integer (should it be by the way?). When I create the object I use:
NSNumber *timestampNumber = [NSNumber numberWithInt:timestamp];
[newAnimation setValue:timestampNumber forKey:#"timestamp"];
Get the NSInteger value from NSNumber
Like
NSInteger timestampNumber = [[NSNumber numberWithInt:timestamp] integerValue];
// then use this integer
[newAnimation setValue:timestampNumber forKey:#"timestamp"];
// or in
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"timestamp == %d", timestampNumber];

Resources