Building a SearchView with UISearchBar and UITableView
Background
I’ve been working away on some iPhone programming lately and one of this
first things I wanted to add to my app was a view for searching. What I
wanted was to have a view that loads with the curser in the
UISearchBar ready to go and to only load the results when the user
presses the ‘Search’ button. The rest of this blog post will go through
putting all this together. At the end you will have a Search View very
similar to the one in the Flixster
App
and hopefully the knowhow to customize it further. If you would rather
skip the step by step and jump right to the code be my
guest.
Search View Requirements
On load have the curser in the UISearchBar ready for user input.
Search is only done once the ‘Search’ button is pressed.
When entering the query any previous results should not be
clickable.
Here’s a look at what we’re going to end up with:
As a side note, if you’re just looking for a simple type-ahead style
search (kind of like what is used in the App Store or Contacts App) you
might want to take a look at the Search Bar and Search Display
Controller that can be added from Interface Builder. I found it super
easy to use for the simple case just described, but very difficult to
customize for anything else.
Getting Started
I’ll leave it up to you to do the basic setup for your app, I started
with a Tab Bar application for mine but you can use whatever you like. I
then created a Nib for the Search View and a corresponding
SearchViewController.h/m that extends from UIViewController (more on
the code for these files later on). With that done we jump into
Interface builder to drop our UISearchBar and UITableView into our
Nib. It should look something like what I have here:
Next up we want to add some IBOutlets in our SearchViewController.h so
that we can refer to the UI elements we just added from our code. I am
going to make these properties as per the Memory Management
Guidelines
from Apple. I’m also going to define a NSMutableArray to hold the data
to display in the UITableView.
If you didn’t get XCode to generate this file for you make sure you
include the import for UIKit.h.
Now we will quickly jump back to Interface Builder and hook those
IBOutlets up before we forget. You’ll also want to make the
UISearchBar and UITableView delegate to the SearchViewController
so that we can handle the callbacks there.
With the Nib all set up lets make sure we synthesize those properties in
SearchViewController.m and release the variables in our dealloc method.
I also snuck a little bit of code into viewDidLoad and
ViewDidAppear; the former just initializing the tableData
NSMutableArray and the later making our UISearchBar first responder.
Making it the first responder causes the UISearchBar to get focus as
soon as the view loads so that the user can start entering their query
right away.
That’s a pretty good start, lets make sure it builds and see what we get
when we run our app before going on.
Implementing the Protocols
We made the SearchViewController the delegate for both the
UISearchBar and the UITableView so are going to implement the
UISearchBarDelegate and UITableViewDataSource Protocols. First we
need to add the Protocols to the SearchViewController.h header file.
Now we implement the methods in SearchViewController.m. There are a
number of callback methods defined by the UISearchBarDelegate Protocol
but we’re only interested in three: searchBarTextDidBeginEditing,
searchBarCancelButtonClicked and searchBarSearchButtonClicked.
This method is called whenever the UISearchBar gets focus. When this
happens we want to show the ‘Cancel’ button (animated:YES makes it slide
in nicely) and disable the UITableView.
When the ‘Cancel’ button is pressed we want to clear the UISearchBar
text and hide the button. We also want the UISearchBar to
resignFirstResponder status so that the keyboard hides and then enable
the UITableView.
The last UISearchBarDelegate Protocol method is the callback for the
‘Search’ button being pressed. This is where we actually perform the
search and add the results to the UITableView. The rest of this method
implementation is the same as when the ‘Cancel’ button is pressed.
Finally we need to implement the UITableViewDataSource Protocol
methods. I’m not going to go into a whole lot of detail here since
there’s lots of
infoout
there
on implementing a
UITableView.
We’ve done lots of work now and it’s probably a good idea to make sure
everything still builds. You should see something like this when you run
the app:
At this point we’ve hit all three marks in the requirements I outlined
earlier and we could call it quits. We could, but I think we could do a
little bit more to help make the UITableView actually seem like it’s
disabled when you go to search.
Fading out the UITableView
If you take another look at the Flixster
App
or even the initial screenshot I have in this post you will notice that
when you are in ‘search mode’ the background of the screen is faded
black. This effect helps to show the user that the UITableView is in
fact disabled.
To get this behaviour I add and remove another UIView and adjust the
opacity in an Animation so that in fades in smoothly. The first thing we
need to do is create an instance variable and property for this
disableViewOverlay as I called it and initialize it when the view
loads.
I’ll leave it to you to figure out what to put in
SearchViewController.m. Now that we have this UIView all set up all we
have to do is fade it in when the UISearchBar gets focus. This was
actually really easy to do, I just needed to add the
disableViewOverlay as a subview and then use
beginAnimations/commitAnimations for the fading.
At the end of searchBarTextDidBeginEditing we added the code to fade
in the disableViewOverlay, then at the end of
searchBarCancelButtonClicked and searchBarSearchButtonClicked we
remove the disableViewOverlay.
If you’ve been following along you might notice a bit of a code
smell coming from these last
three methods. There’s a lot of code duplication which I don’t really
like so I actually re-factored these three methods and created another
method that all of them can call. The resulting re-factored code looks
like this:
That cleans things up nicely. Now when you run the app you should have
the main view fade out smoothly when you enter the UISearchBar just
like mine below:
Conclusion
There we have it, a nice Search View that you have full control over.
I’ve included the full code with inline comments below, have at it! If
you have any suggestions or feedback please [leave a
comment](http://jduff.github.com#comments!
Comments
comments powered by Disqus