Use NSPredicate in Searchable UITableView

Searchable? Not, you mean filterable. TableView supposes already have data in it, what you want to do is to provide a text box on top to accept keyword then FILTER the data in table.


Before diving into TableView/SearchBar all those UI magic, get ready to NSArray basic filtering skill.
For fitlering NSString array: //[cd] means case and diacritic insensitive lookups according to doc.

     NSPredicate* p = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", keyword];
     self.filteredList = [self.list filteredArrayUsingPredicate:p];

NSDictionary type Model lookup is also supported in NSPredicate. Given your model has key named ‘title’:

     NSPredicate* p = [NSPredicate predicateWithFormat:@"title contains[cd] %@", keyword];
     self.filteredList = [self.list filteredArrayUsingPredicate:p];

Now, back to UI magic.


From O’Reilly book Programming iOS4 by Matt Beuburg:

The first question is how to make the search filed (textbox) appear along with the table view, same as Apple’s own app such as the Contracts app. (Indeed, this is such a common arrangement that if you drag a UISerachBar onto a UITableView in a nib, the search field becomes the table’s header view and a UISearchDisplayController is created for you automatically.) Another feature of Apple’s standard interface is that the search field isn’t initially showing. To implement this, we scroll to the first actual row of data when the table view appears.

To create all of those by code:

    UISearchBar* b = [[UISearchBar alloc] init];
    [b sizeToFit];
    b.delegate = self;
    [self.tableView setTableHeaderView:b];
    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
                          atScrollPosition:UITableViewScrollPositionTop  animated:NO];
    UISearchDisplayController* c = [[UISearchDisplayController alloc] initWithSearchBar:b contentsController:self];
    [b release];
    self.sbc = c;  // property type of UISearchDisplayController
    c.delegate = self;
    c.searchResultsDataSource = self;
    c.searchResultsDelegate = self;
    [c release];

In UITableview datasource code, switch to

(tableView == sbc.searchResultsTableView)? [self.filteredList count] : [self.list count];

Implement searchBarSearchButtonClicked method:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
    [self filterArrayBy:searchBar.text];
    [self.sbc.searchResultsTableView reloadData];


- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
    [self filterArrayBy:searchText];

- (void)filterArrayBy:(NSString*) keyword
    // title is a key in my ArrayListData(NSDictionary), for pure NSString filtering, use SELF instead
    NSPredicate* p = [NSPredicate predicateWithFormat:@"title contains[cd] %@", keyword];
    self.filteredList = [self.list filteredArrayUsingPredicate:p];
    [self.sbc.searchResultsTableView reloadData];


// to solve the problem of list becomes empty whenever user starts typing
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
    self.filteredList = self.list;

// live search
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
    [self filterArrayBy:searchText];


Pictures are from this post, but the technology used here is a little bit different.


One thought on “Use NSPredicate in Searchable UITableView

  1. Nice tutorial. I didn’t work for me though. I think I’ll follow Apple’s sample code Table Search. By the way you have a duplicate declaration of `- (void)searchBar:textDidChange:`

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s