Escape nonbreaking space as argument in NSPredicate - ios

I want to filter out empty records, but I am not able to remove the records which has no data but a series of space..
I have a Entity A with attribute "name" . I want to query all those objects of Entity A which has some text value for attribute name and not "series of space",In other words I need to incorporate this in the query -->
[name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet].length!=0
But all I could was check the length of string INCLUDING the whitespace which is not right.
I am using-->
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"name!=' ' or name.length!=0 "];
Your suggetions are welcome.

you can trim the string and check for the lenght of the string like this:
NSString *trimmedString = [aRecordString stringByTrimmingCharactersInSet:[[NSCharacterSet characterSetWithCharactersInString:#" "]]];
if (trimmedString.lenght > 0) {
// the string if valid or at least is not just a spaces string
}
else {
// the string is not valid or was just a spaces string
}
so if you want to apply this check in a predicate you can use a predicate with block:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
// do your checks here and return TRUE or FALSE if the ovject match your criteria
}];

If you're trying to remove objects where a specific string attribute contains only spaces, use a regex-based predicate, and then delete whatever objects you find.
A fetch with a predicate like this would find all of those objects:
NSPredicate *reqPredicate = [NSPredicate predicateWithFormat:#"attributeName matches ' +'"];
Once found, use -[NSManagedObjectContext deleteObject:] to delete the resulting objects.

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 and BEGINSWITH with CloudKit : Field value type mismatch

I have a table "Store" with the attributes "name" of type String (indexes checked for sort query and search).
I want to execute a SQL like query to find all stores with name beginning with a substring.
So I tried this predicate :
NSPredicate *pred = [NSPredicate predicateWithFormat:#"ANY name BEGINSWITH %#",substring];
CKQuery *query = [[CKQuery alloc]initWithRecordType:#"Store" predicate:pred];
CKQueryOperation *queryOperation = [[CKQueryOperation alloc] initWithQuery:query];
queryOperation.desiredKeys = #[#"name",#"category"];
NSMutableArray *results = [[NSMutableArray alloc] init];
queryOperation.recordFetchedBlock = ^(CKRecord *record) {
[results addObject:record];
};
queryOperation.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *error) {
//my own code
}
[publicDatabase addOperation:queryOperation];
I have this error :
<CKError 0x1887a540: "Invalid Arguments" (12/1009); "Field value type mismatch in query predicate for field 'name'"> for query : <CKQuery: 0x18882650; recordType=Store, predicate=ANY name BEGINSWITH "mysubstring">
My guess is that you need to get rid of the "ANY".
The ANY and SOME aggregate operators may be combined with the IN and
CONTAINS operators to perform list membership tests.
So ANY is for lists (Arrays). Since 'name' is a String, it is not a list, hence the mismatch error: "Field value type mismatch in query predicate for field 'name'"
Wild guess...try:
[NSPredicate predicateWithFormat:#"ANY {'name','category'} BEGINSWITH %#",substring];
That may be an incorrect reversal of key/value but it might work.
A completely different approach would be to create a third field called "nameAndCategory", append the two strings and add them to the field. Then figure out how to do the full text search (tokenized string search) with the predicate:
[NSPredicate predicateWithFormat:#"self contains '%#'",substring];
or
[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"self contains '%#'",substring];
But perhaps the only sure approach is to do two searches and combine the results.

how to compare only selected strings in a text with given input in objective-c

i know that the question sounds wears.I couldn't find a better way to put it so i will take my time to explain the question i m struggling with.
I have an iPhone app that takes input from user.And i got a plist ( i will convert it to a online database soon) What i currently do is this. I compare my input string with ingredients part of items in my plist.
This is the plist format
<array>
<dict>
<key>category</key>
<string>desert</string>
<key>numberOfPerson</key>
<string>3</string>
<key>recipeImage</key>
<string>asd.jpg</string>
<key>time</key>
<string>15</string>
<key>recipeName</key>
<string>Puding</string>
<key>recipeDetail</key>
i compare the input with recipeIngredients.But what my codes do is not what i need.If the comparison turns true i just list every item from my plist that contain the input ingredients.I can filter through selected recipes but what i want is this: Unless there is a full match up with input and ingredients i do not want to show it.
The problem is this. I got my recipe ingredients like this format 1 spoon of sugar, 1 spoon of salt, 100g chicken.
The user enter inputs like - salt , sugar. chicken so i can not fully compare it.It will never be the same so i can not show anything.
How can i accomplish this.
i m open for any kind of suggestions.
This is how i compare
results = [arrayOfPlist filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSDictionary *_dataRow = (NSDictionary *)evaluatedObject;
return ([[[_dataRow valueForKey:#"recipeIngredients"] lowercaseString] rangeOfString:[searchText lowercaseString]].location != NSNotFound);
}]];
where searchText is my input.
First of all, you'll never know if there is a typo in user input.
But what you can do is before you compare two strings, you can do a little bit trimming for a given character set.
There is a method in NSString class called :
- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set
If you want to get rid of . or - characters, you need to specify them in your character set. Than, you can compare two strings.
Using -[NSPredicate predicateWithFormat:] you can do database-esque string comparisons. For instance, you could try
[NSPredicate predicateWithFormat:#"recipeIngredients CONTAINS[cd] %#", searchText]
Check out https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html the section called "String Comparisons"
EDIT: if the user will be searching multiple things at once, like "chicken, noodle," you can be a little more fancy and do:
NSArray *tokens = [[searchText componentsSeparatedByCharactersInSet:NSCharacterSet.alphanumericCharacterSet.invertedSet] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"length > 0"];
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:#"recipeIngredient CONTAINS[cd] (ANY %#)", tokens]
You should split up the searchText into an array by using -componentsSeparatedByString:#",", and then loop through the array to see if the recipeIngredients contains any of the ingredients in the searchText array. In order to work out if the query contains every single ingredient, you can create an integer inside of the block and increment it everytime you have a match. If the number of matches is equal to the number of ingredients, then you can go from there.
The code below builds up a predicate that boils down to "ingredients contains sugar and ingredients contains chocolate"
NSArray* recipes = #[
#{#"recipeIngredients": #"sugar flour chocolate"},
#{#"recipeIngredients": #"sugar chocolate"},
#{#"recipeIngredients": #"flour chocolate"},
#{#"recipeIngredients": #"chocolate"},
];
NSString* search = #"sugar, chocolate";
// split the ingredients we have into an array of strings separated by ',' or ' '
NSArray* haves = [search componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#", "]];
// Build a list of recipeIngredients CONTAINS have
NSMutableArray* ands = [NSMutableArray new];
for(NSString* have in haves)
{
if(have.length > 0)
{
[ands addObject:[NSPredicate predicateWithFormat:#"recipeIngredients CONTAINS[cd] %#", have]];
}
}
// String all the haves into a single long ... AND ... AND ... predicate
NSPredicate* predicate = [NSCompoundPredicate andPredicateWithSubpredicates:ands];
// Apply the predicate
NSArray* filtered = [recipes filteredArrayUsingPredicate:predicate];

NSPredicate Format String with unexpected result

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.

Resources