Tutorial details

Database storage using SQLite | App Code for Sale | Preview

Database storage using SQLite | iOS Tutorial

This tutorial is based on the free component Database Storage SQLite
Download

Overview PAGE TOP

Add or Find a Contact using SQLite

The focus of this tutorial is the creation of a somewhat rudimentary iPhone iOS application that is designed to store contact information (names, addresses and telephone numbers) in a SQLite database. In addition to data storage, a feature will also be implemented to allow the user to search the database for the address and phone number of a specified contact name. Some knowledge of SQL and SQLite is assumed throughout the course of this tutorial.

Project Set-Up PAGE TOP

Create new project in XCode that will use single view application template and name it as ‘AddOrFindAContact’. Ensure that you have the Use Automatic Reference Counting option checked.

1.png

Select the project name and then click the Build Phases tab on the right. Click the “+” button shown in the Link Binary with Libraries section to add the libsqlite3.dylib library to it. After this, the library will be added to the project.

2.png
338.png

Programming: PAGE TOP

Go to the AppDelegate.h file and add the UINavigation Controller, add property and synthesize it.

@property (strong, nonatomic) UINavigationController *navigationController;

Go to the AppDelegate.m file and modify the following code for the UINavigation Controller:

@synthesize navigationController = _navigationController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

Go to the ViewController.xib and add the Heading Label and two buttons. Name the Label as Add or Find a Contact: and two button as Add a Contact, Find a Contact. Add the referencing outlets and touchUpInside methods for the two buttons

4.png
597.png

After linking references and methods the ViewConroller.h looks like:

@interface ViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIButton *addContactButton;
- (IBAction)onClickAddButton:(id)sender;
@property (strong, nonatomic) IBOutlet UIButton *findContactButton;

- (IBAction)onClickFindButton:(id)sender;
@end

Go to the ViewController.m file, in a ViewDidLoad method add title:

  self.title = @"Add/Find a Contact";

Add New File Right Click on the Classes folder and select the UIViewController Class and give the name to the class as AddOrFindContactViewController as shown below:

6.png
In AddOrFindContactViewController.h add a Bool variable to identify whether user want to add or Find a contact:

@property (nonatomic, assign) BOOL isAddContact;

AddOrFindContactViewController.m, synthesize the isAddContact Variable:
@synthesize isAddContact = _isAddContact;

Go to the ViewController.m file and implement the following methods:

- (IBAction)onClickAddButton:(id)sender {
    AddOrFindContactViewController *addOrFindViewController = [[AddOrFindContactViewController alloc] init];
    addOrFindViewController.isAddContact = YES;
    [self.navigationController pushViewController:addOrFindViewController animated:YES];

}
- (IBAction)onClickFindButton:(id)sender {
    AddOrFindContactViewController *addOrFindViewController = [[AddOrFindContactViewController alloc] init];
    addOrFindViewController.isAddContact = NO;
    [self.navigationController pushViewController:addOrFindViewController animated:YES];
}

Go to the AddOrFindContactViewController.xib, add label Name and link to .h file, add text field name and link to the .h file. Do the same for the Address and Contact no. field. Add labels and text field for the address and contact no. Also add the Status Label and link to .h file, a button and link to .h file name it as findOrAddButton.

![7.png](/images/tutorial/7.png)

After Linking the AddOrFindContactViewController.h looks:

@interface AddOrFindContactViewController : UIViewController
{
}
@property (strong, nonatomic) IBOutlet UITextField *name;
@property (strong, nonatomic) IBOutlet UITextField *address;
@property (strong, nonatomic) IBOutlet UITextField *phone;

@property (strong, nonatomic) IBOutlet UILabel *status;
@property (strong, nonatomic) IBOutlet UILabel *addressLabel;
@property (strong, nonatomic) IBOutlet UILabel *contactLabel;
@property (strong, nonatomic) IBOutlet UILabel *nameLabel;
@property (strong, nonatomic) IBOutlet UIButton *findOrAddButton;
@property (nonatomic, assign) BOOL isAddContact;

- (void)saveData:(id)sender;
- (void)findContact:(id)sender;

Import SQLite framework in .h file:

#import "sqlite3.h"

And also create the instance of SQLite database:

    @interface AddOrFindContactViewController : UIViewController
{
    sqlite3 *contactDB;
    NSString *databasePath;
}
In ViewDidLoad Method of Class AddOrFindContactViewController.m add the following code:

    - (void)viewDidLoad
{
    NSString *docsDir;
    NSArray *dirPaths;

    // Get the documents directory
    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    docsDir = [dirPaths objectAtIndex:0];

    // Build the path to the database file
    databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"contacts.db"]];

    NSFileManager *filemgr = [NSFileManager defaultManager];

    if ([filemgr fileExistsAtPath: databasePath ] == NO)
    {
        const char *dbpath = [databasePath UTF8String];

        if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
        {
            char *errMsg;
            const char *sql_stmt = "CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)";

            if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
            {
                status.text = @"Failed to create table";
            }

            sqlite3_close(contactDB);

        } else {
            status.text = @"Failed to open/create database";
        }
    }

    [super viewDidLoad];
    if(self.isAddContact)
    {
        self.title = @"Add Contact";
        [self.findOrAddButton setTitle:@"Add" forState:UIControlStateNormal];
        [self.findOrAddButton addTarget:self action:@selector(saveData:) forControlEvents:UIControlEventTouchUpInside];
    }
    else{
        self.title = @"Find Contact";
        [self.findOrAddButton setTitle:@"Find" forState:UIControlStateNormal];
        [self.findOrAddButton addTarget:self action:@selector(findContact:) forControlEvents:UIControlEventTouchUpInside];
        self.addressLabel.frame = CGRectMake(15, 70, 290, 90);
        self.addressLabel.numberOfLines = 4;
        [self.addressLabel setFont:[UIFont systemFontOfSize:17]];
        self.address.hidden = YES;
        self.contactLabel.hidden = YES;
        self.phone.hidden = YES;
        self.addressLabel.text = @"";
        self.nameLabel.text = @"Enter Name:";
    }

}

The code in the above method performs the following tasks:

•Identifies the application’s Documents directory and constructs a path to the contacts.db database file.

•Creates an NSFileManager instance and subsequently uses it to detect if the database file already exists.

•If the file does not yet exist the code converts the path to a UTF-8 string and creates the database via a call to the SQLite sqlite3_open() function, passing through a reference to the contactDB variable declared previously in the interface file.

•Prepares a SQL statement to create the contacts table in the database.

•Reports the success or failure of the operation via the status label.

•Closes the database and performs a memory clean up.

The saving of contact data to the database is the responsibility of the saveData action method. This method will need to open the database file, extract the text from the three text fields and construct and execute a SQL INSERT statement to add this data as a record to the database. Having done this, the method will then need to close the database. In addition, the code will need to clear the text fields ready for the next contact to be entered, and update the status label to reflect the success or otherwise of the operation. Implementation of saveData method:

- (void)saveData:(id)sender {
    sqlite3_stmt    *statement;

    const char *dbpath = [databasePath UTF8String];

    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
    {
        NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO CONTACTS (name, address, phone) VALUES (\"%@\", \"%@\", \"%@\")", name.text, address.text, phone.text];

        const char *insert_stmt = [insertSQL UTF8String];

        sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
        if (sqlite3_step(statement) == SQLITE_DONE)
        {
            status.text = @"Contact added";
            name.text = @"";
            address.text = @"";
            phone.text = @"";
        } else {
            status.text = @"Failed to add contact";
        }
        sqlite3_finalize(statement);
        sqlite3_close(contactDB);
    }
}

As previously indicated, the user will be able to extract the address and phone number for a contact by entering the name and touching the find button. Ultimately, the Touch Up Inside event of the find button will be connected to the findContact method, the code for which is outlined below:

    - (void)findContact:(id)sender {

    const char *dbpath = [databasePath UTF8String];
    sqlite3_stmt    *statement;

    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
    {
        NSString *querySQL = [NSString stringWithFormat: @"SELECT address, phone FROM contacts WHERE name=\"%@\"", name.text];

        const char *query_stmt = [querySQL UTF8String];

        if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
        {
            if (sqlite3_step(statement) == SQLITE_ROW)
            {
                NSString *addressField = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
                //address.text = addressField;

                NSString *phoneField = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
                //phone.text = phoneField;
                self.addressLabel.text = [NSString stringWithFormat:@"Address is %@ and Contact Number is %@", addressField, phoneField];
                status.text = @"Match found";

            } else {
                self.addressLabel.text = @"";
                status.text = @"Match not found";
                address.text = @"";
                phone.text = @"";
            }
            sqlite3_finalize(statement);
        }
        sqlite3_close(contactDB);
    }
}

This code opens the database and constructs a SQL SELECT statement to extract any records in the database that match the name entered by the user into the name text field. The SQL statement is then executed. A return value of SQLITE_ROW indicates that at least one match has been located. In this case the first matching result data is extracted, assigned to NSString objects and displayed in the appropriate text fields. As an alternative, a while loop could have been constructed to display all matching results. For the purposes of keeping this example simple, however, we will display only the first match. The code then updates the status label to indicate whether a match was found, and closes the database. Having implemented the appropriate methods be sure to save both the AddOrFindContactViewController.h and AddOrFindContactViewController.m files before moving on to the user interface design phase.

Building and Running the application: PAGE TOP

The final step is to build and run the application. Click on the Build and Run button located in the toolbar of the main Xcode project window. Assuming an absence of compilation errors, the application should load into the iOS Simulator environment. Enter details for a few contacts, pressing the Save button after each entry. Be sure to check the status label to ensure the data is being saved successfully. Finally, enter the name of one your contacts and click on the Find button. Assuming the name matches a previously entered record, the address and phone number for that contact should be displayed and the status label updated with the message “Match found”: Tap on the ‘Add a Contact’

12.png
Enter the details, which will be saved on the local DB and then tap on ‘Add’
13.png
“Contact Added”
14.png
Navigate to ‘Find a Contact’ from home screen
15.png
Search for the contact, which you added before. It fetches the address and contact details from DB.
16.png
Search by entering the wrong details, here is the message it shows:
17.png

8 Comments Leave a comment

Please login in order to leave a comment.

Newest first
  • dhruw.tara@gmail.com 2013-08-14 07:39:38 Thread #48

    Where is source code????

    • Chupa Team 2013-08-14 11:31:57

      http://www.chupamobile.com/products/details/499

  • vnSerg 2013-01-13 10:28:27 Thread #27

    Great! But where is source code?

    • Chupa Team 2013-01-30 10:50:15

      http://www.chupamobile.com/products/details/499

  • dikidin 2012-11-13 21:01:20 Thread #24

    I think that is tutorial is excellent, but, i can't run my program.. can I download the source code??

    • Chupa Team 2013-01-30 10:50:26

      http://www.chupamobile.com/products/details/499

  • mrimadali 2012-05-18 11:50:42 Thread #9

    Good one..Worthy to read..

  • obiSerra 2012-05-15 08:20:42 Thread #8

    nice tutorial

!

Sign-in to your Chupamobile Account.

The Easiest way to Launch your next App or Game.

Join Chupamobile and get instant access to thousands of ready made App and Game Templates.

Creating an account means you’re okay with Chupamobile’s Terms of Service and Privacy Policy.