How to create a searchable UITableView in iOS 9


Creating searchable table views was always a bit of a nightmare before iOS 8. Until then we had to use a UISearchDisplayController, and sometimes a separate UISearchBar object that needed to be scrolled in and out of vision to make it look elegant. We also had to conform to several protocols. All this was cumbersome and error prone.

Since iOS 8 we can use something much easier called the UISearchController. Sadly the Apple documentation isn’t exactly forthcoming on how to use this thing. Let me show you how to do it in this article.

I’m using Objective-C, Xcode 7, a bit of KVO magic and a simple array for dummy values (no Core Data). If you prefer video instructions, check out my 4 part screencast on building this project over here.

Project Setup

Let’s start with a single view application template in Xcode. We want to add two new classes to our project, both of which will inherit from the UITableViewController. I’ll call one “Table View” and the other one “Search Results”. The first will hold the numbers 1 to 20 written out as strings, and the other one will show us filtered results when users search through those values. Feel free to delete the ViewController h and m files – we won’t need those.

In the storyboard I’ll delete the single view controller and add two table view controllers instead. The first one will be embedded into a navigation controller, to which we’ll add a search button at the top. Hook up an action so that we can do something when the user taps it (i.e. present the search bar and let them search).

Add the right classes for each table view controller, and make sure to give each table view cell a unique reuse identifier (I’ll use “Cell” for both). I also recommend to change each cell style from “Custom” to “Plain” so that we can populate it with some text later.

Screen Shot 2015-10-21 at 09.28.25

The second table view controller won’t be connected to anything – we’ll instantiate it manually. For us to do that we’ll need a storyboard ID. Anything will do here. I’ll call mine “SearchResults”. It’s only appropriate.

Screen Shot 2015-10-21 at 09.43.48

One last thing: make the navigation controller the initial view controller – otherwise we’ll end up with a black screen and nothing else. That would be un-fun.

Screen Shot 2015-10-21 at 09.44.50

Setting up the Main Table View Controller

Before we go any further I’ll make sure our table view has something to display. An NSArray property with some dummy values will do nicely. We can create those with a custom initialiser:

@property (nonatomic, strong) NSArray *values;

// ...

- (NSArray *)values {
    if (!_values) {
        _values = @[@"One", @"Two", @"Three", @"Four", @"Five",
                    @"Six", @"Seven", @"Eight", @"Nine", @"Ten",
                    @"Eleven", @"Twelve", @"Thirteen", @"Fourteen", @"Fifteen",
                    @"Sixteen", @"Seventeen", @"Eighteen", @"Nineteen", @"Twenty"];
    return _values;

In the screencast I’ll show you a nifty way to create several thousand dummy values with the help of a number formatter. Check it out if you’re interested.

To make sure the table view displays only one section and the correct amount of rows, we’ll tweak the data source methods accordingly. They have a pragma warning there by default as a reminder that something needs to be changed here. Feel free to delete them and make them look like this:

#pragma mark - Table view data source (Main Table View)

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.values.count;

Now we need to populate the table view with some data. The following method is called for each cell. We can use the indexPath property to deduce which value needs to be displayed in each cell. We’ll do that by extracting the correct object from our array and show the text in the cell’s text label:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    // Configure the cell...
    cell.textLabel.text = [self.values objectAtIndex:indexPath.row];
    return cell;

Make sure to change the dequeueReusableCellWithIdentifier to the same value as you set in the storyboard.

One last thing we should do to make our table view elegant and operational is to deselect a row if it has been tapped. By default when we tap a cell it will highlight, but the highlight never goes away until we select another cell. Read: super ugly. One final method will take care of it: this one is called when someone selects a cell:

All we’ll do is deselect said cell. Run the app and see if it’s working. You should see a simple table view with the numbers 1 to 20 displayed.

Adding the Search Controller

We need a property to hold a reference to our new search controller. And much like with the array above, we’ll use a custom initialiser to configure it at this point:

This content is for members only.

Demo Project

Here’s the code I’ve built in the screencast I spoke about earlier. It’s pretty much the same as what we’ve discussed here:

Further Reading

Leave a Reply