NSPredicate predicateWithFormat for NSMetaDataQuery in iOS - ios

I need to append my custom string into NSPredicate.
So I wrote following codes.
self.query = [[NSMetadataQuery alloc] init];
[self.query setSearchScopes: [NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K like '%#*'",NSMetadataItemFSNameKey,whereAreYou];
NSLog(#"%#",pred.description);
[self.query setPredicate:pred];
However when I test it , it only return following value.
kMDItemFSName LIKE "%#*"
the placeholder %# is not append correctly. It only showing %# sign.
How can I do that?

Format arguments inside quotation marks are not expanded by predicateWithFormat,
therefore #"%K like '%#*'" does not work.
This should work:
NSString *pattern = [NSString stringWithFormat:#"%#*", whereAreYou];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K LIKE %#", NSMetadataItemFSNameKey, pattern];

Related

Obj-C - NSPredicate - Can I implement an 'or IF' statement?

I'm trying to write a filter with NSPredicate that states:
IF field_Uid contains 47 and field_Target contains 202...display these items
This portion works great. However, I also want to show items in which the reverse is true, eg.:
OR IF fieldUid contains 202 and fieldTarget contains 47...display these
items also
Right now, I have the following code:
NSString *targetedUser = #"47";
NSString *myID = #"202";
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"fieldUid contains[cd] %#", targetedUser];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"fieldTarget contains[cd] %#", myID];
//E.G. See p3 & p4 being the reverse?
// NSPredicate *p3 = [NSPredicate predicateWithFormat:#"fieldUid contains[cd] %#", myID];
// NSPredicate *p4 = [NSPredicate predicateWithFormat:#"fieldTarget contains[cd] %#", targetedUser];
NSCompoundPredicate *p = [NSCompoundPredicate andPredicateWithSubpredicates:#[p1, p2/*, p3, p4*/]];
NSArray *filtered = [self.messages filteredArrayUsingPredicate:p];
How would I write in the latter? I'm not sure how to do it without making the statement requiring all 4 lines to be true? (See commented out code - I've left it in so you can see what I mean...)
Just combine two compound "and" predicates using a compound "or" predicate.
You have the first compound "and" predicate in your question. Create the 2nd compound "and" predicate as needed.
Now use [NSCompoundPredicate orPredicateWithSubpredicates:] passing in the two "and" compound predicates.
you can also use
NSString *targetedUser = #"47";
NSString *myID = #"202";
//this will easily fix your issue, simply update your query like this
NSPredicate *p = [NSPredicate predicateWithFormat:#"(fieldUid contains[cd] %# AND fieldTarget contains[cd] %#) OR (fieldUid contains[cd] %# AND fieldTarget contains[cd] %#)", targetedUser, myID, myID, targetedUser];
NSArray *filtered = [self.messages filteredArrayUsingPredicate:p];

how to work with NSPredicate

I am try to search word which contain "EVBAR02". Can any body help me in this case. Here is Array Directory.
Here is code.
`NSMutableArray *filteredListContent = [NSMutableArray arrayWithArray:arrayGallery];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"imageUrl CONTAINS[cd] EVBAR02"];
[filteredListContent filterUsingPredicate:predicate];`
arrayGallery = (
{
imageId = "04";
imageUrl = "/article/THEV-EVBAR04.jpg";
},
{
imageId = "02";
imageUrl = "/article/THEV-EVBAR02.jpg";
},
{
imageId = "06";
imageUrl = "/article/THEV-EVBAR06.jpg";
}
)
But Its not working. What to do?
The ...WithFormat part of predicateWithFormat: works the same way like stringWithFormat:
NSString *searchString = #"EVBAR02";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl CONTAINS[cd] %#", searchString];
Or literally in single quotes:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl CONTAINS[cd] 'EVBAR02'"];
The quotation is required as described in the documentation:
String constants must be quoted within the expression—single and
double quotes are both acceptable, but must be paired appropriately
(that is, a double quote (") does not match a single quote ('))
Vadian is right.
And if you want to pass the field name as a parameter, use %Kin place of %#:
NSString *searchField = #"imageUrl";
NSString *searchString = #"EVBAR02";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K CONTAINS[cd] %#", searchField, searchString];
You have to set single quotes in your search string :
NSPredicate *predicate = [NSPredicate predicateWithFormat : #"imageUrl CONTAINS[cd] 'EVBAR02' "]
NSString *myString = #"EVBAR02";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl
contains[cd] %#", myString];
NSMutableArray *arrResult =[filteredListContent filteredArrayUsingPredicate:predicate];
There is no need of NSString stringWithFormat, directly use NSPredicate predicateWithFormat as below:
NSMutableArray *filteredListContent = [NSMutableArray arrayWithArray:arrayGallery];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl CONTAINS[cd] 'EVBAR02'"];
[filteredListContent filterUsingPredicate:predicate];
Hope it will help:)

NSPredicate not filtering as desired

Consider the following array:
NSArray *dataValues = #[#"Foo[0]", #"Foo[1].bar"];
And the following regex pattern, predicate and expected output:
NSString *pattern = #"Foo[0]";
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"SELF BEGINSWITH[cd] %#", pattern];
NSArray *results = [dataValues filteredArrayUsingPredicate: predicate];
NSLog(#"matches = %ld", (long)results.count);
This prints 1 in the console as expected. If we change the pattern to:
NSString *pattern = #"Foo\\[[0-9]\\]";
I would expect this to print 2 in the console, but it prints 0. I have double escaped the outer square brackets to allow them to be parsed and expect to find strings that have the numbers 0 to 9 inside the brackets to match this expression.
I have checked the regex against the following site, which does work correctly:
http://regexr.com/3bcut
I have no warnings/errors in Xcode (6.4, 6E35b) running against the iOS 8.4 iPhone 6 Plus simulator, but why does my regex not filter as expected?
You could try this depending on what your needs are:
NSArray *dataValues = #[#"Foo[0]", #"Foo[1].bar"];
NSString *pattern = #"Foo[*]*";
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"SELF LIKE %#", pattern];
NSArray *results = [dataValues filteredArrayUsingPredicate: predicate];
NSLog(#"matches = %ld", (long)results.count);
You could go a little more basic and use
NSMutableArray *results = [NSMutableArray array];
for (NSString *str in dataValues) {
if ([str rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location != NSNotFound) {
if ([str hasPrefix:#"Foo["]) {
[results addObject:str];
}
}
}
NSLog(#"matches = %ld", (long)results.count);
After raising a TSI with Apple (well, who uses those things anyway?) they said I simply needed to use MATCHES instead of BEGINSWITH, which is only used for string matching - whereas I am trying to match on a regex.
My predicate should have therefore read:
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"SELF MATCHES[cd] %#", pattern];

How to use a compound NSPredicate?

I would like to know how if at all to use a compound NSPredicate?
I have made an attempt as follows however the currentInstall array is exactly the same at the start as it is after the predicate has been applied.
NSArray *currentInstall = [coreDataController filterReadInstalls:selectedInstallID];
NSArray *tempArray = [currentInstalls filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"cHR == 0"]];
currentInstalls = [tempArray copy];
NSPredicate *predicateAreaString = [NSPredicate predicateWithFormat:#"area == %#", [myFilter objectForKey:#"area"]];
NSPredicate *predicateBString = [NSPredicate predicateWithFormat:#"stage == %#", [myFilter objectForKey:#"area2"]];
NSPredicate *predicateCString = [NSPredicate predicateWithFormat:#"partCode == %#", [myFilter objectForKey:#"area3"]];
NSPredicate *predicateDString = [NSPredicate predicateWithFormat:#"doorNo CONTAINS[cd] %#", [myFilter objectForKey:#"door"]];
NSPredicate *predicateEString = [NSPredicate predicateWithFormat:#"doorDesc CONTAINS[cd] %#", [myFilter objectForKey:#"doorDesc"]];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:#[predicateAreaString, predicateBString, predicateCString, predicateDString, predicateEString]];
NSMutableArray *filteredArray = [NSMutableArray arrayWithArray:[currentInstalls filteredArrayUsingPredicate:compoundPredicate]];
currentInstalls = [filteredArray mutableCopy];
There doesn't seem to be anything obviously wrong with the way you have implemented NSCompundPredicate. If you are not trying to And or Not predicates then I would say it is something wrong with your predicate formats and how they match the array you are filtering.
I would try to use just 2 of the predicates to create an NSCompundPredicate then get that working or see what is causing your issue. NSHipster also has some good info about NSPredicates.

NSPredicate search LIKE

i'm trying to filter a string array with this predicate:
[NSPredicate predicateWithFormat:#"SELF LIKE[c] '#*!%d'", aNumber]
Every string which is like #WILDCARD!ANY_NUMBER is valid.
But it doesn't work :(
Can you help me?
EDIT:
NSString *pattern = [#"#*!" stringByAppendingFormat:#"%d", numberVariable];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pattern];
NSArray *filteredArray = [anArray filteredArrayUsingPredicate:pred];
The array anArray contains Strings like #0!-1 (numberVariable is -1) but the array filterdArray is empty. So the regex doesn't work.
EDIT:
My Solution:
NSString *pattern = [#"#.*!\\" stringByAppendingFormat:#"%d", numberVariable];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pattern];
NSArray *filteredArray = [anArray filteredArrayUsingPredicate:pred];
To find all strings that look like "#ANY_CHARACTERS!ANY_NUMBER" with an arbitrary number, you need the "MATCHES" operator with a regular expression:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", #"#.*!\\d+"];
NSArray *filtered = [yourArray filteredArrayUsingPredicate:pred];
If you have a specific number aNumber and want to find all strings of the form
"#ANY_CHARACTERS!<aNumber>", then the following should work:
NSString *pattern = [#"#*!" stringByAppendingFormat:#"%d", aNumber];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF LIKE %#", pattern];
NSArray *filtered = [yourArray filteredArrayUsingPredicate:pred];
The problem with your
[NSPredicate predicateWithFormat:#"SELF LIKE[c] '#*!%d'", aNumber]
is that %d inside quotation marks is not replaced by aNumber.

Resources