No Result when searching through an NSArray of NSDictionaries using NSPredicate - iphone

Hey,
I have an Array of NSDictionaries (e.g. [tempArray addObject:[[[NSMutableDictionary alloc] initWithObjects:someArray forKeys:keys] autorelease]]; ) and when I try to search through it with NSPredicate it keeps giving me 'No Results'. (TempArray becomes self.patientList)
I have no compile-time warnings or errors, and if I NSLog([self.filteredArray count]); then it returns 0 as well.
Here is my relevant code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(first contains[cd] %#)", self.searchBar.text];
self.filteredArray = [self.patientList filteredArrayUsingPredicate:predicate];
return [self.filteredArray count];
self.patientList and self.filteredArray are types NSMutableArray and NSArray respectively (changing self.filteredArray to NSMutableArray doesn't help).
I have tried using == instead of contains as well. Using #"SELF contains[cd] %#" only returns an item when the full item is typed (i.e. if the key 'name' is #"Bob" then if I type in Bob it will display it, but not when I type Bo or ob).
I'm really stumped on this one.
Thanks in advance!

Apparently first is a reserved word when using predicates. From Apple's documentation:
The following words are reserved:
AND, OR, IN, NOT, ALL, ANY, SOME,
NONE, LIKE, CASEINSENSITIVE, CI,
MATCHES, CONTAINS, BEGINSWITH,
ENDSWITH, BETWEEN, NULL, NIL, SELF,
TRUE, YES, FALSE, NO, FIRST, LAST,
SIZE, ANYKEY, SUBQUERY, CAST,
TRUEPREDICATE, FALSEPREDICATE
Just change your key to something else, firstName perhaps, and it will work.

You can use "like" instead:
first like[c] *%#*

At first glance, it seems correct. So then: do your dictionaries actually have a key called first? And if they do, does it match the case exactly?

Related

Compound Predicate not working

NSMutableArray *arrayOfPredicates=[[NSMutableArray alloc]init];
[self.attendeeListSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
NSString *userId=[obj userId];
[arrayOfPredicates addObject:[NSPredicate predicateWithFormat:#"userID == %#",userId]];
}];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:arrayOfPredicates];
[request setPredicate:compoundPredicate];
I am setting this compound predicate for multiple userIds in an array and i need to get the Users from those User ids using OR.
The above is not working but when I'm hardcoding using
NSPredicate *predicate1=[NSPredicate predicateWithFormat:#"(userID like[cd] %#)
OR (userID like[cd] %#)",#"sheetal2", #"sheetal3"];
[arrayOfPredicates addObject:predicate1];
Now this is working..Can anyboady tell whats the problem with my code..
Thanks
In your first code the predicate uses ==. In the second code the predicate uses LIKE[cd]. Because the userID is an NSString, using LIKE is generally a better way to tell the predicate to compare the values, but the real difference is that the second approach is case and diacritic insensitive and the first approach requires an exact match.

how can i use predicateWithFormat for two different Class

i need to imlement search with to different class ons is Song and the other one is Album. etch one of them is represent song/album with his property (name,url,etc..).
now i am using this code to search song from my songArray by searching the name property, i need to also be able to search in the albumArray, also in the name property.
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
// Update the filtered array based on the search text and scope.
// Remove all objects from the filtered search array
[self.filteredSongArray removeAllObjects];
// Filter the array using NSPredicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF._songName contains[cd] %#",searchText];
filteredSongArray = [NSMutableArray arrayWithArray:[_myDataMgr.songArray filteredArrayUsingPredicate:predicate]];
}
so my qustion is how can i tell the the predicate to look also in the AlbumArray
thank you all.
UPDATE:
i ran another predicate on the AlbumArray and after i got the results i added the two arrays. thank your replay was very helpful!
You can filter the array contents like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(songName CONTAINS[cd] %#)", searchText];
[self.filteredSongArray addObjectsFromArray [_myDataMgr.songArray filteredArrayUsingPredicate:predicate]];
No need to add SELF in predicate....
Hope this helps...!!!

Configuring an NSPredicate with multiple conditions

I'm not certain how one would go about "cascading" several conditions into an NSPredicate.
I'm fairly new to Core Data and not sure if that's the right way to achieve what I am looking to do.
Here is what I am trying to do:
There is a Photo object that has a whereTook relationship to a Location object, which has an inverse of photosTookThere.
The Photo in turn has an NSNumber attribute called isFavourite.
I'd like to configure an NSFetchRequest that will first check that photosTookThere exists and if so, check each resulting Photo object and return only the ones that are set as favourites.
Here is the code so far:
request.entity = [NSEntityDescription entityForName:#"Location" inManagedObjectContext:context];
request.sortDescriptors = [NSArray arrayWithObject[NSSortDescriptorsortDescriptorWithKey:#"locationId" ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:#"photosTookThere.#count != 0"];
How would I cascade the second condition into the predicate and return the correct results?
Just put each condition inside of parentheses and connect them with AND.
[NSPredicate predicateWithFormat:#"(photosTookThere.#count != 0) AND (isFavourite == %#)", [NSNumber numberWithBool:YES]];
I'd also recommend changing the name of your "whereTook" relationship to "location", and your "photosTookThere" to simply "photos", that's more in line with convention.
I eventually was able to solve this using a subquery:
request.predicate = [NSPredicate predicateWithFormat:
#"(photosTookThere.#count !=0) AND SUBQUERY(photosTookThere, $Photo, $Photo.isFavourite==1).#count >0"
];
You can very simply use AND and OR in your predicate much like you would if you were specifying a "where" condition in an SQL statement. To check for a NULL, which it looks like you want when comparing against "whereTook", you can compare to nil (whereTook = nil).

NSPredicate for fetching keywords that are in a string

In core data I have an entity called keyword with a property 'text'. I want to find all keyword objects that are contained in a particular sting.
I tried:
[NSPredicate predicateWithFormat:#"%# contains[c] text", myString];
But that crashes. It seems like if it will only work if it's reversed.
The predicate works on the entity, so you have your predicate reversed. Since your entity's text property contains a single word, you'd split the string into multiple words and then test:
// This is very simple and only meant to illustrate the property, you should
// use a proper regex to divide your string and you should probably then fold
// and denormalize the components, etc.
NSSet* wordsInString = [NSSet setWithArray:[myString componentsSeparatedByString:#" "]];
NSPredicate* pred = [NSPredicate predicateWithFormat:#"SELF.text IN %#", wordsInString];
I think you're doing in reverse direction.
Try this.
[NSPredicate predicateWithFormat:#"text contains[cd] %#", myString];

NSFetchRequest on to-many-relationship excluding some objects does not work as expected

i struggling around NSFetchRequest these days.
My data model look like this:
Post <->> Category
Now i need a fetch request to get all posts where the category.name attribute is not "xxx".
Looking at the documentation for NSFetchRequest is should be:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"NONE category.name == %#", categoryName]
But this results in an empty list (the request is used by NSFetchedResultsController in an UITableView.
The docs say:
NONE
Specifies none of the elements in the following expression. For example, NONE children.age < 18. This is logically equivalent to NOT (ANY ...).
If i invert my predicate to
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY category.name == %#", categoryName]
the list contains exactly the objects i want to be excluded from that list.
What am i missing here?
thanks in advance
The predicate form you have is correct.
The simplest explanation is that you have no objects that match the "#"NONE category.name == %#" predicate. That would explain why the inverse works.
I suggest that you:
Log the predicate with NSLog and see what the predicate actually is each time
Fetch all Post objects compare the count of objects returned with the count of objects returned by the "ANY" predicate. If they are the same then...
...log the category.name values to see if any of them do match the "NONE" predicate.
I think that should allow you to find the problem.