19
votes

I'm developing an iOS application with iOS SDK 6.0 and XCode 4.5.2. My target development is 4.3.

I'm using Core Data to manage my data. Now I have this NSPredicate to search shops:

if ((shopSearchBar.text != nil) && ([shopSearchBar.text length] > 0))
{
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@",shopSearchBar.text];
    [fetchRequest setPredicate:predicate];
}

This is Shop entity:

enter image description here

I have to convert name to lowercase and see if it contains shopSearchBar.text in lowercase format.

Example:

I have these four shops:

  • Shop1
  • shop 1
  • my shop
  • Shop

If user search text is 'shop', it must returns all of them.

Do you know how to do that?

3

3 Answers

69
votes

This is how I've solved my problem:

if ((shopSearchBar.text != nil) && ([shopSearchBar.text length] > 0))
{
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@",
                              shopSearchBar.text];
    [fetchRequest setPredicate:predicate];
}
2
votes

(a) You could add a column to your repository - lowercaseName - and every time you save a Shop, save a lowercase only version of it's name. Then your predicate is just compare :)

(b) However, if all you want is to do a case insensitive compare try this :

if ((shopSearchBar.text != nil) && ([shopSearchBar.text length] > 0))
{
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name LIKE[cd] %@",shopSearchBar.text];
    [fetchRequest setPredicate:predicate];
}

This is also diacritic insensitive compare. Look at the String Comparison section of this docs page for more options.

(a) gives you faster queries but more complicated code. (b) gives you very simple save methods but (slightly) slower queries

2
votes

You should be able to use NSPredicat's predicateWithBlock: method:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *bind) {
return [self.name compare:shopSearchBar.text options:NSCaseInsensitiveSearch] == NSOrderedSame; }];