NSPredicate Parsing - ios

I have a simple predicate driving me crazy.
NSString *name;
NSDate *myDate;
-(void)fetch:(NSString *)name Date:(NSDate *)myDate
{
...
//predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name = %# AND myDate = %#",name,myDate];
[req setPredicate:predicate];
}
-(void)fetch2:(NSString *)predicateStr
{
...
//predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateStr];
[req setPredicate:predicate];
}
////// call #1/////
[self fetch:name Date:myDate]; //WORKS
////// call #2/////
NSString *predicateStr = [NSString stringWithFormat:#"name = %# AND myDate = %#",name,myDate];
[self fetch2:predicateStr];
//Call#2 doesn't work - Can't parse Date ?? Aren't they identical? The parameters are the same, no change in values. Note, the Date parameter is the problem, the NSString parameter works fine without the Date.

No, they're not the same.
For Call #1, here's what you're passing in to +predicateWithFormat::
#"name = %# AND myDate = %#"
For Call #2, here's what you're passing in to +predicateWithFormat::
#"name = Some Name AND myDate = 2012-10-17 8:05:42 PM -0800"
The first one is a valid predicate format string, and thus it works. The second is not a valid predicate format string, and thus it fails.

Related

Building an NSPredicate from objects in an array throws "Unable to parse the format string" error

I have an NSArray of strings that need to be used to construct an NSPredicate format. This predicate is then used for a core data fetch request.
For some reason the following produces a "Unable to parse the format string" error.
Any ideas on how I can get this to work?
NSArray *multipleStrings = [multipleText componentsSeparatedByString:#","];
NSMutableString *predicateString = [[NSMutableString alloc] init];
for (NSString *sizeString in multipleStrings) {
[predicateString appendFormat:#"AND ANY containerType.typeID.intValue == %i ", sizeString.intValue];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF IN %# %#", self.group.people, predicateString];
I would have hoped it would have created a dynamic predicate format like the following:
#"SELF IN %# AND ANY containerType.typeID.intValue == 2 AND ANY containerType.typeID.intValue == 4 AND ANY containerType.typeID.intValue == 10"

NSString as float in CoreData predicate

I have CoreData Table with NSString field. But in the filter I need to be interpreted as float.
fieldName.floatValue does not give the correct result. If any way to do this without changing the field type in the table ?
Edit:
Data is:
company = "CompanyName";
date = "2016-01-17";
value = "379.76";
My predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"value.floatValue > 2000"];
But value 379.76 enters the result. Using value.floatValue all the same values are compared as strings.
TNX
If you know value is not negative, you can use this trick:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"abs:(value) > 2000"];
The abs: forces SQLite to treat the value attribute as a number.
Alternatively, add zero to it (which works for negative numbers):
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"add:to:(value,0) > 2000"];
I think you should change String type to Number, this is the easiest way.
You can use this predicate:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [[evaluatedObject value] floatValue] > 2000; // Change id to your Class
}];
But this predicate can not be used with CoreData. So you should store the fetch result to an array, then use this predicate with it.
//Try with this.
// '>' will apply when 'value' is number. So, I first put your values in an array. Only then, I can apply the predicate.
NSString *company = #"CompanyName";
NSString *date = #"2016-01-17";
NSString *value = #"379.76";
NSArray *dataArray = #[#(value.floatValue),#(379.76),#(379),#(200)];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self > %f",200.0];
NSArray *array = [dataArray filteredArrayUsingPredicate:predicate];
//output:#(379.76),#(379.76),#(379)
Try this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"value > 2000"];

NSPredicate how to filter object fields

How do I filter an array of objects by a specific field?
My code:
NSMutableArray *inputArray = [[NSMutableArray alloc]init];
Person *person = [[Person alloc]init];
person.first_name = #"John";
[inputArray addObject: person];
person = [[Person alloc]init];
person.first_name = #"Jack";
[inputArray addObject: person];
NSString *expression = [NSString stringWithFormat:#"SUBQUERY(inputArray, $object, $object.first_name CONTAINS[c] J"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:expression];
NSMutableArray *filteredArray = [[inputArray filteredArrayUsingPredicate:predicate]mutableCopy];
NSLog(#"Count should be 2: %lu",(unsigned long)filteredArray.count);
This is the error I get:
'NSInvalidArgumentException', reason: 'Unable to parse the format string "SUBQUERY(inputArray, $object, $object.first_name CONTAINS[c] J"'
This is a basic example for testing. The real-case scenario is that I have an array of objects (Person or whatever) and I want to filter that array by certain fields within the objects ie first_name. As the user types we will filter a visual list based on what they type - so typing "J" would yield 2 results, but then when they type "Jo" only "John" appears on the list.
What am I doing wrong?
EDIT
Still doesn't seem to be working. Updated code:
DOVisitor *vi = [inputArray objectAtIndex:0];
NSLog(#"NAME: %#",vi.first_name);
NSPredicate *firstNamePredicate=[NSPredicate predicateWithFormat:#"first_name LIKE[cd] %#", #"Jo"];
NSPredicate *lastNamePredicate =[NSPredicate predicateWithFormat:#"last_name LIKE[cd] %#", #"Jo"];
NSPredicate *finalPredicate = [NSCompoundPredicate orPredicateWithSubpredicates : #[firstNamePredicate, lastNamePredicate]];
NSArray *filteredArray = [[inputArray filteredArrayUsingPredicate:finalPredicate]mutableCopy];
NSLog(#"Count should be 1: %d", [filteredArray count]);
I get an empty array back. However when I print the first object of the inputArray the console logs "John"
EDIT
Using CONTAINS instead of LIKE does the trick
You don't need a subquery for this, this is a very basic filter.
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"first_name CONTAINS[cd] %#", #"j"];
Let us say you have Person object and you are trying to search for both firstName and lastName, then you can use:
NSPredicate *firstNamePredicate=[NSPredicate predicateWithFormat:#"firstName LIKE[cd] %#", #"Jo"];
NSPredicate *lastNamePredicate =[NSPredicate predicateWithFormat:#"lastName LIKE[cd] %#", #"Jo"];
NSPredicate *finalPredicate = [NSCompoundPredicate orPredicateWithSubpredicates : #[firstNamePredicate, lastNamePredicate]];
The final Predicate is generated by oring the previous predicates. So even if Jo is present in firstName or lastName, that Person object will pass the predicate test.
Edit:
Get filtered objects with above predicate
NSArray *filteredArray = [inputArray filteredArrayUsingPredicate:finalPredicate];

NSPredicate predicateWithFormat for NSMetaDataQuery in iOS

I need to append my custom string into NSPredicate.
So I wrote following codes.
self.query = [[NSMetadataQuery alloc] init];
[self.query setSearchScopes: [NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K like '%#*'",NSMetadataItemFSNameKey,whereAreYou];
NSLog(#"%#",pred.description);
[self.query setPredicate:pred];
However when I test it , it only return following value.
kMDItemFSName LIKE "%#*"
the placeholder %# is not append correctly. It only showing %# sign.
How can I do that?
Format arguments inside quotation marks are not expanded by predicateWithFormat,
therefore #"%K like '%#*'" does not work.
This should work:
NSString *pattern = [NSString stringWithFormat:#"%#*", whereAreYou];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K LIKE %#", NSMetadataItemFSNameKey, pattern];

Replacing content in string within NSPredicate

I am trying to replace text within an array and for some reason the code doesn't work, despite no line alert by Xcode, it causes it to crash.
i.e. "name, 2013"
stripping ", 2013"
to result in
"name"
What am I doing wrong, for the life of me I can't work it out and desperately need help on this?
The specific line in question is "case ITSectionTypeAuthor:"
- (void)setUpDataByType:(ITSectionType) type andFilter:(NSString *)filter {
self.type = type;
self.filter = (filter)? filter : #"";
[self.sections removeAllObjects];
NSPredicate *predicate = nil;
NSString *descriptorKey = #"genus";
NSArray *rowData = [[ITData sharedObject] animals]; //coming form singleton
//generate predicate
switch (self.type) {
case ITSectionTypeAuthor:
predicate = [NSPredicate predicateWithFormat:#"describer componentsSeparatedByString:#", "] objectAtIndex:0] LIKE %#", filter];
break;
default:
predicate = nil;
break;
}
I think the problem is in this line:
predicate = [NSPredicate predicateWithFormat:#"describer componentsSeparatedByString:#", "] objectAtIndex:0] LIKE %#", filter];
You're creating an objective-c string:
#"describer componentsSeparatedByString:#"
and then a C-string:
"] objectAtIndex:0] LIKE %#"
That can't be right, can it? I think you want:
predicate = [NSPredicate predicateWithFormat:#"describer LIKE %#", [[filter componentsSeparatedByString:#", "] objectAtIndex:0]];

Resources