NSPredicate Format String with unexpected result - ios

I am learning NSPredicate and I have an example with problem.
NSArray * array = #[#{#"name":#"KudoCC"}, #{#"name":#"123"}] ;
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"name == '%#'", #123] ;
NSArray * result = [array filteredArrayUsingPredicate:predicate] ;
The parameter here is #123, it is NSNumber type. I think it works the same as #"name == '123'", but the result is nil, which I expected as #{#"name":#"123"}.
Can somebody tell me why? Thank you in advance.

The document here said,
If you use variable substitution using %# (such as firstName like %#), the quotation marks are added for you automatically.
Quotation marks should be avoided in common cases. If you use something like #"%K == '%#'", you are actually comparing the key with #"%#". Only if you have an array like #[#{#"%#": #"KudoCC"}], you need this way.

Related

How to set predicate for a string attribute holding integer value in core data

How to set predicate for a string attribute holding integer value in core data to get the in-between values in integer.
I am using compound predicate for multiple conditions and a piece of code follows..
NSPredicate *categoryPredicate = [NSPredicate predicateWithFormat: #"rating >= %# AND rating <= %#",ratingFrom.text,ratingTo.text];
[compoundPredicateArray addObject: categoryPredicate ];
"rating" attribute is of type string in database. I need to get the rating between the given range in the ratingFrom & ratingTo textfields.
"1" to "10" should fetch all ratings in between 1 to 10.how can I achieve this, without changing the attribute type to number.
Any help appreciated..Thanks
i am not confirm but try this
convert your values in NSString and put this code
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"string CONTAINS[c] %#",searchText];
Ideally you should change this attribute to be a number rather than a string. But if that's not possible, the following should force CoreData (or rather SQLite) to treat it as a number:
NSPredicate *categoryPredicate = [NSPredicate predicateWithFormat: #"add:to:(rating,0) >= %d AND add:to:(rating,0) <= %d",ratingFrom.text.intValue,ratingTo.text.intValue];
you can try BETWEEN expression:
BETWEEN The left-hand expression is between, or equal to either of,
the values specified in the right-hand side. The right-hand side is a
two value array (an array is required to specify order) giving upper
and lower bounds. For example, 1 BETWEEN { 0 , 33 }, or $INPUT BETWEEN
{ $LOWER, $UPPER }. In Objective-C, you could create a BETWEEN
predicate as shown in the following example:
So your code should look like this:
NSPredicate *betweenPredicate =
[NSPredicate predicateWithFormat: #"rating BETWEEN %#", #[ratingFrom, ratingTo]];
ratingFrom, ratingTo should be NSNumber instances if rating is NSNumber.

add componentsseparatedbystring into a predicate with core data

i have a String stored in an Entity (core data) i want to use an NSFetchedResultsController to get data.
string format: abc,ba,x,s,d. this is an array of IDs saved as string.
i want to get only entities that contains at least an IDs in that string.
the problem is if i use CONTAIN in the predicate and search for "a" i will get a wrong result.
could you please tel me if it's possible to add something like "componentsseparatedbystring" in a predicate so i can iterate and use "in"in the result or if there's an other solution, thanks.
You can use the "MATCHES" operator in a predicate, which does a
regular expression match:
NSString *searchID = #"a";
NSString *pattern = [NSString stringWithFormat:#"(^|.*,)%#(,.*|$)",
[NSRegularExpression escapedPatternForString:searchID]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ID MATCHES %#", pattern];
The pattern (^|.*,)TERM(,.*|$) searches for TERM which is preceded
by either the start of the string or a comma, and followed by the
end of the string or another comma.
First convert your array of ID's into an NSArray:
NSArray *arrayOfIds = [stringOfIds componentsSeparatedByString:#","];
Then use an IN predicate on your fetch:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ID IN %#", arrayOfIds];
this assumes your database column is called "ID", and your comma-separated string of ID's is stringOfIds.
finally i will use a dirty solution: we have 4 possibilities:
string format= a
string format= a,..
string format= ..,a
string format= ..,a,..
so the predicate could be:
[NSPredicate predicateWithFormat:#"(ID LIKE %# OR
ID CONTAINS %# OR
ID CONTAINS %# OR
ID ENDSWITH %#)",
searchedID,
[NSString stringWithFormat:#"%#,", searchedID],
[NSString stringWithFormat:#",%#", searchedID],
[NSString stringWithFormat:#",%#,", searchedID]]
but this is a dirty solution, i really want something cleaner.

NSPredicate with dynamic key and value

I am trying to create a function that searches through my core data stack and return the amount of messages for a desired key/value.
Here is my code:
NSFetchRequest *messagesCountRequest = [NSFetchRequest fetchRequestWithEntityName:#"Message"];
NSEntityDescription *messageCountModel = [NSEntityDescription entityForName:#"Message" inManagedObjectContext:_mainManagedObjectContext];
[messagesCountRequest setEntity:messageCountModel];
NSPredicate *messageCountPredicate = [NSPredicate predicateWithFormat:#"%# == %#", key, value];
[messagesCountRequest setPredicate:messageCountPredicate];
count = (int)[_mainManagedObjectContext countForFetchRequest:messagesCountRequest error:nil];
The problem is that it returns 0 every time. I have located the source of the problem. When have a static key, the predicate looks like this.
key == "value"
When I pass through a dynamic key, it looks like this
"key" == "value"
So the problem appears to be the first set of double quotes around the key that is placed by passing a NSString to the predicate. How would I fix this?
EDIT: For clarity, I need it to be like the first case, that is the one that works.
To substitute a key in the predicate string, you have to use %K, not %#:
[NSPredicate predicateWithFormat:#"%K == %#", key, value];
From the Predicate Format String Syntax documentation:
%# is a var arg substitution for an object value—often a string, number, or date.
%K is a var arg substitution for a key path.
let predicate = NSPredicate(format: "SELF[%#] CONTAINS %#",key,value)
This worked for me

NSPredicate issue with greater than equals

I have a simple NSPredicate which is not giving correct result
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF.data.squareFootage >= %#", filterSquareFootage];
filteredArray = [[filteredArray filteredArrayUsingPredicate:resultPredicate] mutableCopy];
Strangely this works for all 6000>=250, 7000>=250, 8000>=6000. But as soon as squareFootage==10000 the predicate for 10000>=any smaller value is false.
Note: 10000 for squareFootage is a max value fetched using a UISlider.If i reduce value to any smaller value, the predicate gives true as result
Am i missing something here and using predicate incorrectly?
I assume that your property is stored as string and not as number, therefore
the values are compared as strings:
"10000" < "250" < "6000"
Using NSNumber instead of NSString (or alternatively some scalar type as NSInteger) should fix the problem.
If you cannot change the data type of the squareFootage property, then the following
predicate should work:
[NSPredicate predicateWithFormat:#"SELF.data.squareFootage.intValue >= %d", [filterSquareFootage intValue]]
YOU CAN"T COMPARE STRINGS USING =< . if SELF.data.squareFootage is a NSNumber try converting filterSquareFootage to NSnumber or int value and compare them like that.

NSPredicate predicateWithFormat:argumentArray: Only Evaluating First Argument

I'm having some trouble using NSPredicate predicateWithFormat:argumentArray:. In this example, serverIDList is array of strings. Results is an array of NSManagedObjects with an attribute named "flid" which is a string.
NSMutableString *predicateString = [[NSMutableString alloc] init];
[predicateString appendString:#"(flid IN %#)"];
[results filterUsingPredicate:[NSPredicate predicateWithFormat:predicateString argumentArray:serverIDList]];
The problem is that [NSPredicate predicateWithFormat:predicateString argumentArray:serverIDList] evaluates to "flid IN '2155'", which is only the first value of the array serverIDList. I can't seem to get the predicate to evaluate the entire array. Is there something missing here?
Thanks!
[NSPredicate predicateWithFormat:#"(flid IN %#)" argumentArray:serverIDList]
is equivalent to
[NSPredicate predicateWithFormat:#"(flid IN %#)", id1, id2, ..., idN]
where id1, ..., idN are the elements of the array serverIDList.
That should explain why only the first element is evaluated.
What you probably want is
[NSPredicate predicateWithFormat:#"(flid IN %#)", serverIDList]
Remark: I would recomment not to create predicates as strings first. The chances for
quoting or escaping errors are quite high. Use only predicateWithFormat with a
constant format string. If you have to combine predicates dynamically at runtime,
use NSCompoundPredicate.

Resources