NSPredicate and ignore strings with specified format Objective c - ios

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"];

Related

NSPredicate with Multiple Conditions

I am trying to create a NSPredicate with multiple conditions. I've found several solutions, but none of them appear to be working with my method. The best looking one I've found is below.
This is my single predicate method, and it works just fine:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name contains[c] %#",
searchText];
filteredBusinesses = [businesses filteredArrayUsingPredicate:predicate];
Here is my edited version with multiple conditions. I'm not sure whats going wrong. Any ideas?
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"businessArea contains[c] %#",
searchText];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[p1, p2]];
filteredBusinesses = [businesses filteredArrayUsingPredicate:predicate];
You can try this
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:#[p1, p2]];
Addition to #Nikunj's answer, you can also use NSCompoundPredicate for your AND operations like this.
Obj-C - AND
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[predicate1, predicate2]];
Swift - AND
let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2] )
Swift 3 - AND
let predicate1 = NSPredicate(format: "X == 1")
let predicate2 = NSPredicate(format: "Y == 2")
let predicateCompound = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1,predicate2])
Nothing looks wrong in the code you posted, which means the error is probably coming from when you evaluate the predicate by filtering the array.
Since the first predicate works, the problem lies with the businessArea key path.
Filtering the array would throw an exception if:
There's an object in the array that doesn't have a businessArea value (as in, it's not an object that has a -businessArea method)
The object does have a businessArea value, but the value is neither an NSString nor nil
NSCompoundPredicate received a facelift. Just in case someone's looking for a Swift 5+ version:
AND
let predicatesAND = NSCompoundPredicate(andPredicateWithSubpredicates:[pred1,pred2])
OR
let predicatesOR = NSCompoundPredicate(orPredicateWithSubpredicates:[pred1,pred2])
First off, I suspect you may have a flaw in your two basic predicates. Judging by your object name "businesses", it is a collection i.e NSArray, NSSet or NSDictionay of items. In that case, "name contains[c] 'mmm'" has no meaning when evaluated for the whole collection, and should crash. It is missing a collection operator (ANY, ALL, SOME) , e.g. "ANY name contains[c] 'mmm'".
Ah... now I see... you're using the predicate to filter an NSArray, which means the predicate is executed on each item separately. So your predicates are alright.
Now... the simplest way to combine your predicates is at the very format-string level! what's wrong with
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"name contains[c] %# AND businessArea contains[c] %#", nameToSearch, areaToSearch];
If you insist on doing it the hard way, than building your compound NSPredicate should have worked too - only you employed the same searchText to both conditions, which may caused the predicate to never match.
My advice to you, place a breakpoint on the line evaluating the filtered array and stop just before the filtering, and in the debugger print the predicate description, using the debugger command po p1 you will see there what is the final form of your predicate, and will be able to determine if you built it correctly.

Core Data Predicate - Check if any element in array matches any element in another array

I'm trying to use a predicate to filter objects where an intersection exists between two arrays.
The NSManagedObject has an array(Of Strings) attribute named "transmissions". And there is another array(Of Strings) that will contain words to filter by, named "filters".
I'm not sure how to find if any elements in "transmissions" match any element in "filters".
I've tried
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY SELF.transmission in[c] %#",transmissions];
or
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY transmission in[c] %#",transmissions];
However, core data fetches no results where there should be some.
Try this.
NSPredicate *predicate = nil;
NSMutableArray *predicates = [NSMutableArray new];
for (NSString *transmission in transmissions) {
[predicates addObject:[NSPredicate predicateWithFormat:#"transmission == %#", transmission]];
}
if (predicates.count > 0)
predicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
// make fetch request using 'predicate'
You can use the keyword CONTAINS to check an object exists in a collection.
[NSPredicate predicateWithFormat:#"favouriteFilms CONTAINS %#", film]
I believe the same thing can be achieved with IN by switching the LHS and RHS of the predicate. I have only successfully implemented this functionality using CONTAINS however.

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.

NSPredicate Contains with List

I have a list of tags like item 1, item 2 and I want to use an NSPredicate to filter an array if a field matches anything in those items. This doesn't accomplish it:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY tags CONTAINS[c] %#", tag];
results = [results filteredArrayUsingPredicate:predicate];
Use the IN operator followed by the array of tags.
predicate = [NSPredicate predicateWithFormat:#"ANY tags IN %#", theTags];

How to specify range with NSPredicate in Objective C

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];

Resources