NSPredicate with 64-bit integers? - objective-c

I'm trying to use NSPredicate with 64-bit numbers, but for some reason it's failing. I create a predicate with the following string:
[NSString stringWithFormat:#"UID == %qu", theUID]
And it always fails. Yet if I loop through my objects and compare if ( UID == theUID ) I find one that is fine. I'm really confused as to why this isn't working correctly.
Does the above look correct? My predicates work fine for other integers or even strings. But this seems to be failing.
Thanks!
Edit: So strange... so I create my predicate by doing:
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:myString];
Now when I print myString, and then print myPredicate (by doing NSLog(#"%#", blah);) I get:
String: UID == 17667815990388404861 Predicate: UID ==
9223372036854775807
It's the same string, why are these different?

Possibly theUID is not an unsigned value?
A more robust way to build predicates would be to pass in an NSNumber:
NSNumber *theUIDNum = [NSNumber numberWithUnsignedLongLong:theUID];
[NSString stringWithFormat:#"UID == %#", theUID]
This gives you the bonus ability to debug and print out the value of theUINum to make sure it got the transition right.

In your NSPredicate you can use something like this
let myNSNumber = NSNumber(value: theUID)
let predicate = NSPredicate(format: "UID = %i", myNSNumber.int64Value)

Related

NSPredicate with format has to be reversed when two format strings are used

I have a NSManagedObject with the following attributes:
status
kind
priority
Now I want to be able to filter my entity with these attributes respectively. So I would expect that I have to have a predicate along those lines:
status CONTAINS[c] ‘open’
I get really weird results, as soon as I have two variables in my predicate and I have to reverse the order of kind and value in my case so that I get the desired results:
NSString *kind = #"status"; // DEBUGGING
NSString *value = #"open"; // DEBUGGING
// This works although it defies all logic
NSString *predicate = [NSString stringWithFormat:#"('%#' CONTAINS[c] %#)", value, kind];
self.myFilterPredicate = [NSPredicate predicateWithFormat:predicate];
This however, does not work for some reason:
NSString *predicate = [NSString stringWithFormat:#"(%# CONTAINS[c] ‘%#‘)”, kind, value];
I cannot reproduce the exact problem, but generally you should not use stringWithFormat to create predicate. It causes problems as soon as the substituted key or value contain
any special characters like spaces or quotation marks.
A better way is
self.myFilterPredicate = [NSPredicate predicateWithFormat:#"%K == %#", kind, value];
%K is a placeholder to be replaced by a key path such as "status".

NSPredicate to many like a <----->> b----->c

I have entities: Language, Proper and Answer.
model look like Language{A:name(NSString), R:propers(NSSet)} --->> Proper{A:name(NSString), R:answer(Answer)} ---> Answer{A:answer(NSString)}
So, i got NSDictionary with params: {#"key1", #"value1"}, {#"key2", #"value2"}... i
I need create NSPredicate from this dictionary to get all Languages where propers.name = key[i] and propers.answer.answer = value[i] from my NSDictionary.
Example:
C++
level : high
try/catch : yes
typization : static
Java
level : high
try/catch : yes
typization : dynamic
NSDictionary : {level : hight}, {try/catch : yes}, {typization : dynamic}
//make and set NSPredicate to array controller
//array controller arrangedObjects will return Java
Sorry for bad grammar :/
Update
*After 2 weeks of sleepless nights and work on expert system teacher took a laboratory without checking it. Kill me please. Thanks a lot to all of you.*
I am just guessing what you want to do so here is a code:
- (NSPredicate *)constructPredicateWithDictionary:(NSDictionary *)dictionary
{
NSArray *allKeys = [dictionary allKeys];
NSMutableArray *predicates = [NSMutableArray array];
for (NSString *key in allKeys) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SUBQUERY(B, $B, $B.key = %# && $B.C.value = %#).#count > 0", key, [dictionary valueForKey:key]];
[predicates addObject:predicate];
}
//not quite sure what you need so I am guessing
NSPredicate *finalAndPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates]; //if you want all the predicates to be concatenated with and '&&' - logical expression - so all of the subqueries have to be correct
NSPredicate *finalOrPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicates]; //if you want all the predicates to be concatenated with or '||' - logical expression - so any of the subqueries has to be correct
return finalOrPredicate; //return the needed predicate
}
You need from SUBQUERY. Something like:
[NSPredicate predicateWithFormat:#"B.key = %# AND SUBQUERY(B, $B, $B.C.value = %#).#count > 0", key, value];
The SUBQUERY iterates through the objects and you can also have nested SUBQUERYs if you have more than one to-many relationships.
You can use and "ANY ..." but it doesn't work in all cases.

NSPredicate bug when string contains ' in Cocoa Touch

I'm setting the string of my predicate like this:
[NSString stringWithFormat:#"(name like '%#')",name]
but if name contains ' characters, for example if name is "family's" it crashes.
How can I fix this?
You don't need the ' in NSPredicate. They are being inserted automatically.
Just try
[NSPredicate predicateWithFormat:#"(name like %#)",name];
The reason this crashed was because the predicate value was interrupted.
If you create a string with format, like in your example, your going to end up with (name like 'family's'), which obviously can't work.
If you use predicateWithFormat: on the other hand, you can let it handle this itself. It will escape your special characters.
If you don't want/aren't able to use predicateWithFormat, then you can simply replace any apostrophes in your string.
I do this in my app, when checking my UISearchBar control, to see if the user's trying to look for particular CoreData records:
NSString* searchString = self.searchBar.text;
if (searchString.length != 0)
{
searchString = [searchString stringByReplacingOccurrencesOfString:#"'" withString:#"\\'"];
NSString* filter = [NSString stringWithFormat:#"companyName CONTAINS[cd] '%#'", searchString];
NSPredicate* predicate1 = [NSPredicate predicateWithFormat:filter];
// ...etc...
}
(This is a simplified version of a generic function I use, which actually searches CoreData using a variable number of filter strings, which is why I don't use predicateWithFormat directly.)

NSPredicate predicateWithFormat not evaluating format specifier

I have a (to me) curious case with NSPredicate's predicateWithFormat: method.
Using the following I log the description of two NSPredicate instances to the console:
NSNumber *myNumber = [NSNumber numberWithInt:1];
NSString *predicateFormatByHand = [NSString stringWithFormat:#"self MATCHES 'chp%#_img[0-9]+\\.png'", myNumber];
NSPredicate *firstPredicate = [NSPredicate predicateWithFormat:predicateFormatByHand];
NSLog(#"firstPredicate description: %#", firstPredicate);
NSPredicate *secondPredicate = [NSPredicate predicateWithFormat:#"self MATCHES 'chp%#_img[0-9]+\\.png'", myNumber];
NSLog(#"secondPredicate description: %#", secondPredicate);
This outputs:
firstPredicate description: SELF MATCHES "chp1_img[0-9]+.png"
secondPredicate description: SELF MATCHES "chp%#_img[0-9]+.png"
I would expect these descriptions to be the same.
Can someone explain why they are not?
(Following this question I've played with various escape sequences for the embedded single-quotes but when doing so keep having NSPredicate complain that it cannot then parse the format string. I'd be grateful to know what's going on.)
UPDATE: one answer suggested it's an issue with using NSNumber rather than an int, so:
NSPredicate *thirdPredicate = [NSPredicate predicateWithFormat:#"self MATCHES 'chp%d_img[0-9]+\\.png'", [myNumber intValue]];
NSLog(#"thirdPredicate description: %#", thirdPredicate);
I began with this originally, but alas the output is the same:
thirdPredicate description: SELF MATCHES "chp%d_img[0-9]+.png"
(Something means the format specifier is not evaluated.)
The answer is simple: the parser used by NSPredicate assumes that anything inside the quote marks is a string literal, and does not attempt to do any substitutions on its contents. It you need to have a dynamic string value, you will have to build the string before substituting it into the predicate format string, as in your first example.
...because the predicate is not such thing than string.
for any of the predicates you should use two format specifier 100% safety only:
one for the key (%K); and
one for the value (%#);
you cannot format neither the key nor the value when you add them to the predicate. this is why your second (and third) predicates are not formatted inside the value.
you can format the value before you add it to the predicate like:
NSNumber *myNumber = [NSNumber numberWithInt:1];
NSString *string = [NSString stringWithFormat:#"chp%#_img[0-9]+\\.png", myNumber];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", string];
NSLog(#"%#", predicate);
the result is:
SELF MATCHES "chp1_img[0-9]+\\.png"
...and never forget my first sentence: the predicates and the strings are not the same thing.
My interpretation of
%# is a var arg substitution for an object value
in the "Predicate Programming Guide" is that %# can only be used for substituting a value that a Core Data object can be compared against. For example
NSNumber *myNumber = [NSNumber numberWithInt:1];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"count = %#", myNumber];
is perfectly valid if "count" is a Number attribute of the entity. It is similar to binding values to SQLite prepared statements.
If %# could be used for general string formatting in predicates, then there would be no need to have two different format specifiers %K and %# for key paths and values.

Does searching using NSPredicate works on multiple language automatically?

I want to know how searching of a string works in objective C when the iphone application has to support multiple language.
Assuming I have a search function that looks like this currently:
- (int)showSearchResultForQuery:(NSString *)query
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name CONTAINS[cd] %# || address CONTAINS[cd] %#",query, query];
storesFiltered = [[NSMutableArray alloc]initWithArray:[stores filteredArrayUsingPredicate:predicate]];
int count = [storesFiltered count];
if(count > 0)
{
// we have some results
[resultTable reloadData];
}
return count;
}
This piece of code basically accepts a query string and update an array being used by a table using NSPredicate. I want to know, what do i need to take in consideration, if this function has to accepts multiple languages? chinese. english...japanese... will this function still work?
Thanks.
The only thing you need to consider is that the encoding of the strings in the array will be the same as the encoding of the query string.
For example, chinese is sometimes represented in UTF16, so you need to make sure that both the strings in the array and query string are encoded in UTF16.
Everything else will work out of the box.