57

I'm looking for a way to use NSPredicate to set a LIKE condition to fetch objects. In addition to that, an OR would be useful as well. I'm trying to do something where if a user searches "James" I can write an NSPredicate that will do the equivalent of:

select * from users where firstname LIKE '%James%' OR lastname LIKE '%James%';
Peter DeWeese
  • 17,853
  • 8
  • 77
  • 100
randombits
  • 44,546
  • 73
  • 235
  • 411

3 Answers3

127
NSString *_mySearchKey = @"James";
NSPredicate *_myPredicate = [NSPredicate predicateWithFormat:@"(firstname CONTAINS[cd] %@) OR (lastname CONTAINS[cd] %@)", _mySearchKey, _mySearchKey];
Alex Reynolds
  • 94,180
  • 52
  • 233
  • 338
  • 36
    Found ! It means Case & Diacritic insensitive – Pierre de LESPINAY Feb 27 '13 at 13:48
  • 1
    @AlexReynolds why don't you use LIKE ? – onmyway133 Apr 10 '14 at 14:54
  • A better question is: Why should I use LIKE, instead? – Alex Reynolds Oct 17 '14 at 00:40
  • this is not working with empty string @"". Any suggestions? [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", strFilter] not working when strFilter is @"" – Add080bbA May 12 '15 at 11:45
  • Check if the string is empty before running your predicate test, and handle that case separately. http://stackoverflow.com/questions/899209/how-do-i-test-if-a-string-is-empty-in-objective-c – Alex Reynolds May 12 '15 at 18:12
  • This answer will not give results as LIKE does for eg: S% give results starting with S, whereas contains will give results not starting with `S` will result listing containing S, which is not a correct result, whats the solution for that? – iphonic Jun 17 '16 at 14:52
38

The CONTAINS operator will certainly work just fine. If you're looking for a more direct correlation, then you can also use the LIKE operator (* = 0 or more characters, ? = 1 character):

NSString *_mySearchKey = @"James";
NSPredicate *_myPredicate = [NSPredicate predicateWithFormat:@"firstname LIKE '*%1$@*' OR lastname LIKE '*%1$@*'", _mySearchKey];

For reference:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-215868

Tommy
  • 98,579
  • 12
  • 179
  • 201
Dave DeLong
  • 241,045
  • 58
  • 447
  • 497
  • 6
    I know that's a long time ago, but this doesn't work, since NSPredicate doesn't substitute quoted content '%@' will stay '%@'... – Vincent Guerci Apr 03 '11 at 10:33
  • 1
    beginswith[c] does it for me but still, has anyone managed to generate a dynamic LIKE query such as '%@*' – Ege Akpinar Oct 26 '12 at 15:45
  • 10
    The trick to using like is to include the * marks in the argument. ie: `NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K LIKE[cd] %@", kMDItemDisplayName, [NSString stringWithFormat:@"*%@*", appname]];` – Richard H. Nov 26 '13 at 02:22
  • What does the 1$@ do? – shim Dec 22 '15 at 22:20
  • @shim identifies specifically the first argument. Contrast with if the author had just used `%@` twice; in that case he'd have needed to supply `_mySearchKey` twice. E.g. `NSLog(@"%1$@ %1$@", @"Hat");` will output "Hat Hat". – Tommy Feb 22 '17 at 15:31
10

Another possibility

@"firstname beginswith[c] James"

As a nice alternative to contains

Sometimes contains isn't always the right answer

M. Ryan
  • 6,874
  • 10
  • 50
  • 75