Develop a UISearchBar iPhone App

Source

(C) 2012 kevin languedoc (klanguedoc)

The UISearchBar is iOS component in the UIKit that was introduced in version 2.0 of the Cocoa Touch Framework and iOS SDK. The UIControl and protocol have several important features to help a developer to quickly implement a search field in their applications. You can enable a search button, a cancel button and bookmark button. The delegate has methods to interact with which buttons are pressed.

This tutorial will demonstrate how to quickly develop a iPhone app that searches a SQLite database using the UISearchBar text field. The database contains a list of names in separate columns. The app will implement a SQL query to search either field, then display the results in an UITableView.

The whole application is built using a Single View application template. The SQLite database is built using the SQLite Manager in Firefox and sample data is added to the database through the SQLite Manager in Firefox.

Create Database and Sample Data

Create Database
For this example, I will create a SQLite database using SQLite Manager for Firefox, which is a free addon. As the following figure depicts, I create a database titled “dbsearch.sqlite” and one table, “names” to hold a sample of first and last names. Save the file to a convenient location since it will have to be added to the iOS project later. Then I add three columns:

  • id: primary key, int, auto incrementing
  • firstname:varchar
  • lastname:varchar


Using the SQLite Manager, I add some sampling data so that I may perform a search later.

Figure 1 : Creating the SQLite Table
Figure 1 : Creating the SQLite Table | Source
Figure 2 : Add data
Figure 2 : Add data | Source

Create Project

The next step as usual is the create the project. Choose the Single View application template to create a simple iOS iPhone app. Call the app DbSearch like the database and exclude the option to use a Xib which will automatically create a storyboard instead.

Once the project is created, select the project root in the navigator and the Summary page on the right in the IDE. Since I will be working with a SQLite database, I will need to add the appropriate library. Scroll down to the Linked Libraries and Frameworks section. Click on the “+” button to bring up the library selector popover. In the search field, type sqlite and then select the “libsqlite3.0.dylib” library and click “add” to close the popover and add the library to the project. You will have to manually drag the library to the framework group as the IDE just adds it to the Resource group by default.

Next right click on the DbSearch group and select “Add files to …” context menu item and browse to the location where the dbsearch.sqlite file was saved, select the database file and click “Add” to begin copying the database to the project. A second popover will appear where you will need to select the first option “copy items to destination group’s folder (if needed)” to actually the project, which is important otherwise only a reference will be added. Now that the project is setup we can build the storyboard and controller logic.

Develop Storyboard

The storyboard is going to be very simple with only an UISearchBar control, a UITableView and corresponding UITableCell. Switch to the “Windows & Bars” section of the Object Library and drag a UISearchBar onto the Canvas and add it to the top of the Scene. With control selected, open the Attributes inspector and select the following options:

  • Shows Search Results button
  • Shows Cancel button


We won’t need to the other options for this example app. Next add a UITableView UIControl and a UITableCell. superimpose the cell control on the table. With the UITableCell selected add an identifier through the Attributes inspector page. Then drag a connection from the UITableView to the UIViewController proxy (yellow globe or circle on the bar below the the main scene). When you release the mouse button, a popover will appear to allow you to set the delegate and the data source. Set both of them.

Then we will create the IBOutlets, open the Editor assistant by clicking on the tuxedo looking icon in the toolbar. To create the IBOutlets drag a connection (ctrl+drag) using the mouse button to the open header file in the Editor assistant. Releasing the mouse button activates a popover, thus allowing you to create a IBOutlet connection by entering a name for the connection in the appropriate field and clicking on “connect”. Perform this operation for the the UISearchBar and the UITableView.

The UI Layout for the App
The UI Layout for the App | Source

Controller Code

With the interface built and the initial IBOutlets created, we will need to add a variable for a NSMutableArray which will be used to store that data for the UITableView, hence its data source. If you want to manipulate the data in the UITableView, you would interface with its data source. In other words with the NSMutableArray.

The other addition is a method to interface with the database: searchDatabase. This method will need take one argument for the search term. The code for the method will be explained in full in the implementation part. To create the interaction for the UITableView, UITableCel and UISearchBar, we will need to add the appropriate protocols. So for the UISearchBar you will need to include the UISearchBarDelegate which will allow you to implement the searchBarCancelButtonClicked and searchBarSearchButtonClicked methods to respond to the buttons in the UISearchBar. For the UITableView, the UITableViewDelegate and UITableViewDataSource protocols.The code for the header is provided below.

Switching to the implementation file, you will need to define the getter and setter properties using the @synthsize directive. Just below the @implementation ViewController code, add the @synthesize directive followed by the NSMutableArray variable, nameList, and the displaySearch UITableView.

For this example, we will implement two UISearchBarDelegate methods for when the Search button is clicked on the keyboard and also when the Cancel button is clicked on the UISearchBar.

searchBarCancelButtonClicked
The searchBarCancelButtonClicked method will reset not only the UISearchBar field but also its data source and UITableView and dismiss the keyboard. The complete code is provided below.

searchBarSearchButtonClicked
The searchBarSearchButtonClicked method is similar in design to searchBarCancelButtonClicked except that will calls the searchDatabase method.

searchDatabase
This method is the main workhorse of the application. The searchDatabase method provides the interface with the SQLite database by passing the searchTerm argument from the searchBar field. The method locates the database in the Resource folder and if the file exists proceeds to open the database. In the next step, the query is created to search for the searchTerm in either the firstname column or the lastname column. The results are written to the nameList NSMutableArray. The source code is provided below.

numberOfSectionsInTableView
To display the returned results we will need to set up the UITableView delegate and data source. The numberOfSectionsInTableView tells the table how many sections the table will have. Sections are groups of rows. I will set this to 1.

tableView:numberOfRowsInSection
The numberOfRowsInSection tells the table how many rows to display. Here it is custom to indicate the number of elements in the array or data source.

tableView:cellForRowAtIndexPath:indexPath
This method configures the UITableCell by gettting a handle on the cell prototype in the UITableView and assign the value at indexPath of the array to the label property of the cell. This method will be called repeatedly for each row that was defined in the numberOfRowsInSection or the number of objects in the array.

ViewController.h

//
//  ViewController.h
//  DbSearch
//
//  Created by Kevin Languedoc on 12/14/12.
//  Copyright (c) 2012 Kevin Languedoc. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <sqlite3.h>

@interface ViewController : UIViewController<UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate>{
    sqlite3 *db;
}
@property(nonatomic,strong)NSMutableArray *nameList;
@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;

@property (strong, nonatomic) IBOutlet UITableView *displaySearch;

-(void)searchDatabase:(NSString*)searchTerm;
@end

ViewController.m

//
//  ViewController.m
//  DbSearch
//
//  Created by Kevin Languedoc on 12/14/12.
//  Copyright (c) 2012 Kevin Languedoc. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize displaySearch, nameList;

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated{
    [self searchBar].delegate=self;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
    [self searchBar].text=@"";
    [displaySearch reloadData];
    [displaySearch resignFirstResponder];
    [self.view endEditing:YES];
}


-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
    [self searchDatabase:searchBar.text];
    [self searchBar].text=@"";
    [displaySearch reloadData];
    [displaySearch resignFirstResponder];
    [self.view endEditing:YES];
}
-(void)searchDatabase:(NSString*)searchTerm{
    BOOL fileExist;
    NSString *root = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"dbsearch.sqlite"];
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    
    nameList=[[NSMutableArray alloc] init];
    
    
    fileExist = [fileMgr fileExistsAtPath:root];
    
    if(fileExist){
        
        if(!(sqlite3_open([root UTF8String], &db) == SQLITE_OK))
        {
            NSLog(@"An error has occured.");
            
        }else{
            
            NSString * sqlQry = [[NSString stringWithFormat:  @"SELECT firstname, lastname FROM  names where firstname=\"%@\" ", searchTerm] stringByAppendingString:[NSString stringWithFormat:@" or lastname=\"%@\"",searchTerm]];            
            sqlite3_stmt *sqlStatement;
            if(sqlite3_prepare_v2(db, [sqlQry UTF8String], -1, &sqlStatement, NULL) != SQLITE_OK)
            {
                NSLog(@"Problem with prepare statement: %d", sqlite3_errcode(db));
            }
            
            
            
            while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
                
                NSString * concatName = [[ NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,0)] stringByAppendingString:[NSString stringWithFormat:@" %@",[ NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)] ]];
                
                NSLog(@"This is the filename %@",concatName);
                
                [nameList addObject:concatName];
            }
            sqlite3_finalize(sqlStatement);
            sqlite3_close(db);

                        
        }
        
    }
    

}
#pragma mark-
#pragma mark table data source and delegate methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
   
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    
    // Return the number of rows in the section.
    return [nameList count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"displaySearchCell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    NSString * nameObj = [nameList objectAtIndex:indexPath.row];

    cell.textLabel.text = nameObj;
    
    return cell;
}


@end

As the screenshot depicts, when a user enters a name in the search field and performs the search by clicking on the Search button on the keyboard the results are fetched from the database, if any, and displayed in the database. The UITableView is reset before each search.

Figure 3 : Running App
Figure 3 : Running App | Source

More by this Author


Comments 13 comments

Vetranks profile image

Vetranks 3 years ago from Shinjuku-ku, Tokyo, Japan

Hello Kevin, how are you? I wanted to ask best wishes for Christmas and the New Year, and I wanted to ask how you could put this in this tutorial http://hubpages.com/technology/Develop-a-UISearchB...

thank you very much


Vetranks profile image

Vetranks 3 years ago from Shinjuku-ku, Tokyo, Japan


klanguedoc profile image

klanguedoc 3 years ago from Canada Author

Hi Vetranks,

Nice to hear from you. I would like to wish Merry Christmas and Happy New Year. I suppose you have already started the new year in Japan. I hope you are having a good party.

To answer your question, you can add a new view controller like in this tut. or you can add the ISearchBar to the existing UITableViewController. You need to add the necessary protocols to the proper header. There are many ways to add search depending on your needs.

Kevin


durul profile image

durul 3 years ago from maryland, US

Could you share sample code. Because I update your other project DBTUITableView. but It doesn't work.

Thanks.


klanguedoc profile image

klanguedoc 3 years ago from Canada Author

I will add to the iosdev101.com/downloads


Murad 2 years ago

Yes, I think accessing their data over the nterowk.I am developing a mobile app to go with my web app. I don't want to loose all of the code I've done in PHP, so I'm thinking that I can use Titanium and your tutorials on remote data, XML/RSS and the httpClient function to access a lot of that code and run those php scripts.I'm thinking that I can use a local db to have user input their subdomain and login info. But how do I send this information to the web and receive things like cookies and sessions? Can I set an account id as a global variable?


Sasha 6 months ago

no results all the time


klanguedoc profile image

klanguedoc 6 months ago from Canada Author

Hi Sasha

Sorry for the absence. What can I help u with

Kevin


Sasha 6 months ago

maybe you can share your project

cause I can't get any results


klanguedoc profile image

klanguedoc 6 months ago from Canada Author

SAsha

Send me an email and I'll send you the code


NewUser 5 months ago

Its not working if i am doing it in this project(http://hubpages.com/technology/iOS-5-How-To-Displa...

its not showing search result


NewUser 5 months ago

your code is also not working which you share on https://sites.google.com/site/ios101dev/downloads

its not showing any thing on TableView and in database there are 8 entries

please help


klanguedoc profile image

klanguedoc 6 days ago from Canada Author

NewUser,

Sorry for the late delay in getting back to you. I was away on a project and I kinda left my blog go stale. Again my appologies. This tutorial was developed uisng iOS 5 SDK. What version are you using now as this will have an impact on the code and functionality

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working