4

I would like to search if in the attribute description (an NSString instance) there is a given word.

I tried with this predicate:

[NSPredicate predicateWithFormat:@"description CONTAINS[cd] %@", theWord];

It works, but it finds also sub-words.

For example, given theWord:

Car

it will mach also this description:

A Christmas Carol

Instead, I would like that my predicate will match only a, or christmas, or carol.

(I'm using Core Data and NSFetchRequest.)

Dev
  • 7,027
  • 6
  • 37
  • 65

1 Answers1

14

Something like this?

NSString *matchStr = @".*\\bCarol\\b.*";

NSPredicate *pred =[NSPredicate predicateWithFormat: @"description MATCHES %@", matchStr];

NSArray *arr = @[ 
    @"A Christmas Carol",
    @"Sing",
    @"Song"
];

NSArray *filtered = [arr filteredArrayUsingPredicate: pred];

The trick is the \b metacharacter, which denotes a word boundary in the string. In order to get a backslash "into" the regex pattern string, you have to precede it with another backslash so the compiler understands that there should be a real backslash in the string. Hence the "\\b" in the string.

Also, in order to cover non-English language strings better, you should enable Unicode word boundary detection, by setting the w flag option. The match string will look like this:

NSString *matchStr = @"(?w).*\\bCarol\\b.*"; 
Monolo
  • 18,205
  • 17
  • 69
  • 103
  • 4
    If you're going to be putting user input in there (like `theWord`), I'd recommend escaping it. So make `matchStr` something like `[NSString stringWithFormat:@".*\\b%@\\b.*", [NSRegularExpression escapedPatternForString:theWord]]`. Otherwise, if a user types in "Car.*l", their input will be treated as a regular expression, and could cause a crash if it's an invalid one. – John Gibb Jul 22 '14 at 15:13