B.S.
B.S.

Reputation: 21726

NSPredicate format

I want to filter NSArray with using NSPredicate predicateWithFormat: method. I have some variable, which I want to use several times in this format. I do not want to write it several times. Here is an example:

NSString *someText = @"some text";
NSString *str = [NSString stringWithFormat:
          @"(field1 CONTAINS[cd] %1$@) OR (field2 CONTAINS[cd] %1$@)", someText];
NSLog(@"%@", str);
// prints : (field1 CONTAINS[cd] some text) OR (field2 CONTAINS[cd] some text)

So it works with NSString stringWithFormat:

Can someone explain why it doesn't work with NSPredicate predicateWithFormat: and how to fix it?

[someArray filteredArrayUsingPredicate:
     [NSPredicate predicateWithFormat:
         @"(field1 CONTAINS[cd] %1$@) OR (field2 CONTAINS[cd] %1$@)", 
     someText]];

I receive this exception:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "(field1 CONTAINS[cd] %1$@) OR (field2 CONTAINS[cd] %1$@)"'

Thanks in advance

Upvotes: 1

Views: 1144

Answers (2)

Brian Palma
Brian Palma

Reputation: 641

UPDATE

You're passing a literal string as an argument to -predicateWithFormat: rather than the result of

[NSString stringWithFormat:@"(field1 CONTAINS[cd] %1$@) OR (field2 CONTAINS[cd] %1$@)", someText];

ORIGINAL

Your -stringWithFormat: call provides a formatting string that has 2 placeholders but you only provide one value.

Upvotes: 0

spassas
spassas

Reputation: 4818

The NSPredicate parser does not accept positional specifiers perhaps due to the $ sign used to declare variables. And by the way, using variables could be a solution to your question.

NSString *someText = @"some text";
NSPredicate *predicate = [NSPredicate predicateWithFormat:
         @"(field1 CONTAINS[cd] $someText) OR (field2 CONTAINS[cd] $someText)"]];
NSDictionary *varSub = [NSDictionary dictionaryWithObject:someText forKey:@"someText"];
NSPredicate *filterPredicate = [predicate predicateWithSubstitutionVariables:varSub];

Although it's probably not much shorter than retyping the variable name...

Upvotes: 2

Related Questions