Building an iOS Search Controller

The ABFRealmSearchViewController class creates a controller object that manages a table view and a search bar, to run text search against a Realm object class.

This allows for the creation of a text search interface in as little as 27 lines of code!

The class performs the text search on a background thread (via RBQFetchedResultsController) allowing for non-blocking, as-you-type searching.

The controller is meant to be subclassed. By default, the resultsDataSource and resultsDelegate protocols are set as self, so that the subclass can implement these methods.

You can see the code for ABFRealmSearchController on GitHub.

This tutorial uses ABFRealmSearchViewController v1.2.


Cover image of the ios search controller in action

Overview

Search is an integral part of many mobile apps. Users want to find their information as quickly as possible, especially on mobile. In many cases, search is left out by developers due to how long it can take to implement. This add-on makes it easy to add search to any of your Realm objects based on specific properties.

It’s very fast and non-blocking, revealing results as you type. Let’s get started and create an app that uses this functionality!

You can see the final code on GitHub here.

Get more development news like this

Tutorial

Create a new Xcode project, using the “Single View Application” template. Be sure “Language” is set to Objective-C, and that “Use Core Data” is unchecked.

ABFRealmSearchViewController is available through CocoaPods. (If you don’t have CocoaPods installed, follow their instructions before continuing.) In your terminal, cd to the project folder you just created, and run touch Podfile. To install ABFRealmSearchViewController, simply add the following line to the Podfile you just created:

pod "ABFRealmSearchViewController"

In your terminal, run pod install. This will also install Realm automatically! (If this is your first time using CocoaPods, this could take a while. Future uses will be much faster.)

When it’s done, you’ll need to close the Xcode window and open the xcworkspace file that CocoaPods created, so that you can use the classes inside the pods.

Go to Main.storyboard and delete the view controller that was generated. Drag in a UINavigationController. This will also create a UITableViewController as its root view controller. On your newly added UINavigationController, be sure to check “Is Initial View Controller” in the right side bar.

Go to UINavigationController and make sure intialViewController is checked

Create a class called BlogSearchViewController and have it inherit from UIViewController.

Create BlogSearchViewController file

Go to BlogSearchViewController.h, add #import "ABFRealmSearchViewController.h", and replace the subclass of UIViewController with ABFRealmSearchViewController. When you’re done, the file should look like this:

#import <UIKit/UIKit.h>
#import "ABFRealmSearchViewController.h"

@interface BlogSearchViewController : ABFRealmSearchViewController

@end

Download the sample data that we’ll be using for this tutorial: JHARealmSearchTutorialData. The data contains information about blog posts. Add BlogObject.h, BlogObject.m, blog.json, and emoji.json to your project. Be sure “Copy items if needed” is checked.

Go to main.storyboard, click the UITableViewController and change its “Class” (in the Identity Inspector, at the top right) to BlogSearchViewController.

Rename UITableViewController class to BlogSearchViewController

Go to BlogSearchViewController.m. Add #import "BlogObject.h" to the top. The file should now look like this:

#import "BlogSearchViewController.h"
#import "BlogObject.h"

@interface BlogSearchViewController ()
...

Go to AppDelegate.m and load your blogposts. The code looks like this:

#import "AppDelegate.h"
#import "BlogObject.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Override point for customization after application launch.
  [BlogObject loadBlogData];
  return YES;
}
...

[BlogObject loadBlogData] is a method that will convert the blog.json data into objects in your Realm.

Go to Main.storyboard, click on the table view cell and change its reuseIdentifier to “blogCell”. (Be sure to hit Enter after typing it to confirm.)

Set reuseIdentifier to blogCell

Click on the BlogSearchViewController (called “Root View Controller”), then the attributes tab. For “Entity Name”, type “BlogObject”. For “Search Property”, type “title”. (Be sure to hit Enter after typing each one to confirm it.) Set “Use Contains” to “On”.

Set search controller attributes

Go to BlogSearchViewController.m and add one of the search controller’s data source methods:

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view.
}

...

#pragma mark - ABFRealmSearchControllerDataSource

- (UITableViewCell *)searchViewController:(ABFRealmSearchViewController *)searchViewController
                            cellForObject:(id)anObject
                              atIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"blogCell" forIndexPath:indexPath];
  
  BlogObject *blog = anObject;
  cell.textLabel.text = [blog.title capitalizedString];
  return cell;
}

Now if you run this now, you should see a list of blog posts! You’re pretty much done at this point; grab some coffee or a beer and celebrate! In the next part, we’ll go over how to style this so it looks similar to the example above.

First, create a custom table view cell called BlogPostTableViewCell, inheriting from UITableViewCell. Be sure to check “Also create XIB file”.

Create BlogPostTableViewCell

Go to BlogPostTableViewCell.xib and increase the height of the cell to 88 by clicking and dragging the handle at the bottom. Then add 3 UILabels, which will represent title, emoji, and content. Style them however you’d like! Just be sure to set “Number of Lines” on the content label to 0, so that more than one line of text will show.

Don’t forget to add your “Identifier”! Set it to “blogCell”.

Create BlogPostTableViewCell UI

Next, set up the Auto Layout constraints as shown in the images below. We won’t go into Auto Layout too much in this tutorial, since we only need the basics. If you’re interested in learning more about Auto Layout, check out some of these great resources!

Set up constraints for the emoji label Set up constraints for the title label Set up constraints for the content label

These constraints will let your cell resize to fit any phone and any content, without any work from you!

In BlogPostTableViewCell.h, create IBOutlets for these labels. Call them titleLabel, emojiLabel, and contentLabel.

Create IBOutlets for BlogPostTableViewCell

In BlogSearchViewController.m, import BlogPostTableViewCell.h, and register your nib in viewDidLoad. The code should look like this:

#import "BlogSearchViewController.h"
#import "BlogObject.h"
#import "BlogPostTableViewCell.h"

@interface BlogSearchViewController ()
@end

@implementation BlogSearchViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view.
  self.title = @"Blogs";
  self.tableView.estimatedRowHeight = 88.f;
  self.tableView.rowHeight = UITableViewAutomaticDimension;
  [self.tableView registerNib:[UINib nibWithNibName:@"BlogPostTableViewCell" bundle:nil] forCellReuseIdentifier:@"blogCell"];
}

Now we’ll update the data source method we created in the same file. We will use the cell we created, and set the labels to the correct text:

- (UITableViewCell *)searchViewController:(ABFRealmSearchViewController *)searchViewController
                            cellForObject:(id)anObject
                              atIndexPath:(NSIndexPath *)indexPath
{
  BlogPostTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"blogCell" forIndexPath:indexPath];
  BlogObject *blog = anObject;
  
  cell.titleLabel.text = [blog.title capitalizedString];
  cell.emojiLabel.text = blog.emoji;
  cell.contentLabel.text = blog.content;

  return cell;
}

Go to Main.storyboard and click on the cell in the UITableView. Set its class to BlogPostTableViewCell.

Fire up the app; you’re done!



Realm Cocoa Team