How to specify range with NSPredicate in Objective C - ios

I want to query sqllite table by specifying a range. So it's like give me all records whose id column between 3000 and 3010.
I tried what Apple recommends, but it didn't work. Here is what I tried and failed.
NSPredicate *betweenPredicate =
[NSPredicate predicateWithFormat: #"attributeName BETWEEN %#", #[#1, #10]];
I have 2 strings called start and end. I updated Apple's example as following.
NSPredicate *betweenPredicate =
[NSPredicate predicateWithFormat: #"%# BETWEEN %#", columnName, #[start,end]];
When I executeFetchRequest with the above predicate I get 0 records even though the table has records matching the predicate. Can someone point where I go wrong?

You have to use the %K format specifier for attribute names:
[NSPredicate predicateWithFormat: #"%K BETWEEN %#", columnName, #[start,end]];
If that does not work (I have never used "BETWEEN" for Core Data fetch requests), you
could replace it by the equivalent predicate
[NSPredicate predicateWithFormat: #"%K >= %# AND %K <= %#",
columnName, start, columnName, end];

Related

NSPredicate and ignore strings with specified format Objective c

I have an array with below values:
<__NSArrayM 0x1c804f120>(
Model.sqlite,
Model.sqlite-shm,
Model.sqlite-wal,
iiii,
report,
test,
ttrrr,
tyyyy,
ww,
wwww
)
I want to NSPredicate array and ignore any array content with string format .sqlite and print remaining like below:
<__NSArrayM 0x1c804f120>(
iiii,
report,
test,
ttrrr,
tyyyy,
ww,
wwww
)
I want to know NSPredicate which does this trick.
You can use NOT CONTAINS, and query .sqlite string to filter out
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"NOT (SELF CONTAINS %#)", #".sqlite"];
Found a solution:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"NOT (SELF contains[c] %#)",#".sqlite"];

Replace characters from string stored in database by using NSPredicate

I have phone numbers stored in database in the format like +1-541-634-4210 or +1 (541) 634-4210.
I want to search unformatted number like +15416344210 in the database by using NSPredicate but i unable to form the correct predicate format.
I try something like this
NSString *regex = [NSString stringWithFormat:#"+0123456789"];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"number MATCHES %# == %#",regex,phoneNumber]];
So any ideas on how to achieve that?
Any help is much appreciated. Thanks!
Have you tried using predicate.
Swift
let predicate = NSPredicate(format: "SELF MATCHES %#", "[+][0-9]+")
predicate.evaluateWithObject(phone number)
Objective-C
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", "[+][0-9]+"];
[predicate evaluateWithObject:phoneNumber];
Please update the right string based on your conditions.
Try this:
predicate = [NSPredicate predicateWithFormat:#"number MATCHES %#", [[filter componentsSeparatedByString:#"- "] objectAtIndex:0]];

How to use predicate on object's array of objects values in iOS

I have an Exit object.
Every Exit has an array of Category objects.
Objects look like this :
Category: (id, name)
Exit: (id,name,number,...,NSArray(Categories),...)
I want to use NSPredicate to filter out exits by Category name they have in Category array, but I'm not sure how exactly to write it down.
If I'd wanted to filter out Exits by Exit name, for example, I would do this
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.exitName = %#", name];
NSArray *results = [exits filteredArrayUsingPredicate:predicate];
But I'm not sure how to get into the Categories array and search by Category Name.
Any suggestions ?
Try this
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY SELF.exitName.category_name CONTAINS[c] %#", name];
NSArray *results = [exits filteredArrayUsingPredicate:predicate];
Try this predicate
NSPredicate *matchingCategory = [NSPredicate predicateWithFormat:#"SUBQUERY(categories, $c, name CONTAINS[cd] %#).#count > 0", categoryName];
Explanation
The SUBQUERY() function creates an array of objects which match the given sub-predicate. In this case, that sub-predicate is name CONTAINS[cd] %#. The way it works is by iterating over the collection (first param), assigning the name $c (second param) to refer to each element and then testing to see if the sub-predicate matches that element. If it matches, it's added to the array.
After the SUBQUERY() completes, the array is aggregated using the #count property. If there were any matches (#count > 0), the overall predicate on the exits will match the exit being tested.

NSPredicate too many arguments. Hard to read it

I just faced with some issue that is connected to clear code. I use predicates in many modules of my projects. When I work with core data the NSPredicates are really helpful for retrieving filtered object.
But the predicating is good for logic but not for code readability as I use it.
So let's see on this example:
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(ANY option.playerzoneID == %d) \
AND (ANY option.gameId == %#) \
AND (team.teamID == %#) \
AND (league.leagueID == %#) \",
zoneIdType,
SELECTED_GAME.gameID,
SELECTED_TEAM.teamID,
SELECTED_LEAGUE.leagueID];
When I look on this predicate I am little confused about this structure even in case that this predicate I have written one week ago.
Any suggestion how to make this code more readable?
I think it will be better to have something like this:
[predicate setParametr:#"gameID == %#", SELECTED_GAME.gameID];
[predicate setParametr:#"league.leagueID == %#", SELECTED_LEAGUE.leagueID];
You can explore the following:
+ (NSPredicate *)andPredicateWithSubpredicates:(NSArray *)subpredicates
+ (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)subpredicates
+ (NSPredicate *)notPredicateWithSubpredicate:(NSArray *)subpredicate
With this you can actually form short predicates and join them together with arrays. So, you don't exactly get what you wished for, but its a near shot.
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"(ANY option.playerzoneID == %d)", zoneIdType];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"(ANY option.gameId == %d)", SELECTED_GAME.gameID];
NSPredicate *predicate3 = [NSPredicate predicateWithFormat:#"(ANY team.teamID == %#)", SELECTED_TEAM.teamID];
NSCompoundPredicate *compoundANDPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[predicate1, predicate2, predicate3]];
Read more about these here:http://nshipster.com/nspredicate/
Edit: Using OR Predicates along with AND Predicates:
Let's assume: you have this predicate to add as OR:
NSPredicate *predicate4 = [NSPredicate predicateWithFormat:#"(ANY team.teamName == %#)", SELECTED_TEAM.teamName];
So, you can group your AND and OR predicates into one compound predicate (compoundANDPredicate as shown above) and then use
+ (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)subpredicates
So it becomes:
[NSCompoundPredicate orPredicateWithSubpredicates:#[compoundANDPredicate, predicate4]];

NSPredicate on an NSArray to search for any object

I have an array of objects with names, addresses, tel. nos, etc.
I want to be able to search the array for any occurrence of a term - whether in the name field, the address field, etc.
I have something like this in mind :
-(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.searchResults removeAllObjects];
// Filter the array using NSPredicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",searchText];
searchResults = [NSMutableArray arrayWithArray:[contactArray filteredArrayUsingPredicate:predicate]];
}
This causes an exception "Can't use in/contains operator with collection".
UPDATE. I can now search on up to three fields. When I add a fourth (in any sequence), I get this exception: "Unable to parse the format string ..."
The Predicate code is now:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.narrative contains[c] %# OR SELF.category contains[c] %# OR SELF.date contains[c] OR SELF.name contains[c] %#", searchText, searchText, searchText, searchText];
searchResults = [NSMutableArray arrayWithArray:[allDreams filteredArrayUsingPredicate:predicate]];
Is three a limit of predicate search fields? How do I get around this? Thanks again.
Just use a predicate string that checks for them all:
#"name contains[cd] %# OR address contains[cd] %#"
you can add as many as you want.
The only downside is that you'll need to add the same search string for each field you want to test, which can seem a bit ugly.
If your objects are dictionaries, then there is a way to truly search all values without necessarily knowing their names at compile time, using a subquery.
It works like this:
#"subquery(self.#allValues, $av, $av contains %#).#count > 0"
It uses the #allValues special key (or method call if you prefer) for dictionary objects and uses that to filter any value that contains your search string. If any is found (i.e., the count is positive), the object is included in the results.
Notice that this will examine all values indiscriminately, even those that you don't want to include if you have any in your dictionary.
I think your array item is not pure string, right?
Suppose your array item contains name attribute (even it's a dictionary), you can search it in this way:
NSPredicate * predicate =
[NSPredicate predicateWithFormat:#"name CONTAINS[cd] %# OR name LIKE[cd] %#", searchText, searchText];
here, name can be SELF.name.
HERE's an official document.

Resources