With the release of Core Data for the iOS, most of the time developers should choose to use that to access SQLite because of the higher level of abstraction and ease of development. However there will still be cases where you want to deal with SQLite directly. This tutorial will show you can read and display data from an SQLite database. In Part 2 we will look at how you can update new data.
Create an SQLite database
1. We will be creating a SQLite database of members of the Avengers team.
Call the database Superheroes.
Create a table 'heroes' with the following fields.
CREATE TABLE "heroes" ("serial" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE , "name" VARCHAR, "desc" TEXT)Populate the table with 4 superheroes from the Avengers, namely Iron Man, Thor, Captain America and the Hulk. For 'desc' fill in with whatever details you wish.
Starting a New Project
2. Start a new Xcode project, choose Navigation-based application template. Name the project AvengersDatabase.
3. Create a new view controller to display description of our heroes.
Right click on Classes and choose Add > New File. You will be presented with a New File dialog.
Choose the UIViewController subclass template.
Ensure the option, with XIB for user interface is checked.
On the next page give a name to the controller. Call it HeroViewController
Ensure that the option to create a header file is ticked.
You now have a new view controller class and XIB file in your project.
Move the XIB file to the Resources folder.
4.For our application to use SQLite you need to include the SQLite framework. Right click on the “Frameworks” folder
Click on “Add > Existing Frameworks…”
Browse for “libsqlite3.0.dylib” file and add it to your project.
5.Next we add the database we created to our project. Right click on the “Resources” folder, click “Add > Existing Files…”, navigate to the location you created the database and add it.
In the next dialog make sure the Copy item into Destination folder is checked.
Click on Add.
6. Next we are going to create a Hero class where each object will contain the information on each hero. The Hero class will also take care of getting information from the database into the Hero objects.
Right click on Classes and choose Add > New File. You will be presented with a New File dialog.
Select the Objective-C Class template.
Ensure that Subclass of NSObject is showing in the dropdown.
Cick Next
On the next page, name the file, Hero. Ensure the Also Create "Hero.h" is checked
Click Finish
7. Now we will declare and implement our Hero class. We are going to add 2 NSString variables, name and desc. We are going to use the @property keyword to expose for synthesize later. We will have class method whose function is to access the database to get data and populate the Hero objects. We are also going to declare a instance method initHero to initialise our objects. Open the Hero.h in Classes folder and edit it as follows:
@interface Hero : NSObject { NSString *name; NSString *desc; } @property (nonatomic, retain) NSString *name; @property (nonatomic, retain) NSString *desc; +(NSMutableArray *)getHeroes:(NSString *)databaseName; -(id)initHero:(NSString *)heroName desc:(NSString *)heroDesc; @end
8. Next open up Hero.m First we will import sqlite3.h, sythesize the variables and implement the instance method initHero:
#import "Hero.h" #import "sqlite3.h" @implementation Hero @synthesize name, desc;
-(id)initHero:(NSString *)heroName desc:(NSString *)heroDesc{ self.name = heroName; self.desc = heroDesc; return self; }
9. GetHeroes Class Method
This is where much of the magic happens. We will implement a class method whose utility is to open the SQLite database, read the data from the database and instantiate Hero objects based on each record retrieved. The Hero objects are stored in NSMutableArray which is returned.
+(NSMutableArray *)getHeroes:(NSString *)databaseName{
NSString *databasePath;
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
//Copy the database over to documents folder if not already done
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:databasePath]){
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
[fileManager release];
}
sqlite3 *database; // Setting up the database object
NSMutableArray *Heroes = [[NSMutableArray alloc] init]; //initialise the Heroes array
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK){
// construct SQL Statement and compile it for faster access
const char *sqlStatement = "select * from heroes";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *rName = [NSString stringWithUTF8String:
(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *rDescription = [NSString stringWithUTF8String:
(char *)sqlite3_column_text(compiledStatement, 2)];
Hero *hero = [[Hero alloc] initHero:rName desc:rDescription];
[Heroes addObject:hero];
[hero release];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return Heroes;
}
10. We are going to modify our RootViewController which will populate the table with the Hero Objects. First Open RootViewController.h and add the following:
@interface RootViewController : UITableViewController {
NSMutableArray *Heroes;
}
@property (nonatomic,retain) NSMutableArray *Heroes;
@end
11. Now we will call GetHeroes when the view is loaded. Open rootViewController.m
and modify method viewDidLoad as follows:
- (void)viewDidLoad { [super viewDidLoad]; self.title = @"Avengers"; Heroes = [Hero getHeroes:@"superheroes.sqlite"]; }
12. With our heroes in our Heroes array it is time to display them to the user.
Modify the the tableview method numbrOfRowsInSection like this:
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return Heroes.count;
}
Next add the following to under the configure the cell comment at cellForRowAtIndexPath:
// Configure the cell. Hero *hero = (Hero *)[Heroes objectAtIndex:indexPath.row]; cell.textLabel.text=hero.name; return cell;
As a good practice release Heroes at method dealloc.
If you run your application now you should see a tableview display of superheroes in the Avengers. The names are drawn from the SQLite database. In part 2 we will look at displaying data from the 'desc' field.

No comments:
Post a Comment