I have seen somewhere that people was struggling to add and handle sqlite database on iPhone development. I would like to help them on giving simple explanation with a project sample here.
If you might have seen some more details easily than this blog in somewhere else, then please don't hesitate to follow up there wherever you are convenient.
Here is the code:
// AppDelegate.h file ########################################################
#import
#import
@interface MySQLLiteSampleAppDelegate : NSObject {
UIWindow *window;
UINavigationController *navigationController;
NSString *databaseName;
NSString *databasePath;
NSMutableArray *elements;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic, retain) NSMutableArray *elements;
-(void) CreateDatabaseIfRequired;
-(void) ReadAndExtractDatabase;
// AppDelegate.m file ########################################################
#import "MySQLLiteSampleAppDelegate.h"
#import "RootViewController.h"
#import "CountryDetails.h"
@implementation MySQLLiteSampleAppDelegate
@synthesize window;
@synthesize navigationController;
@synthesize elements;
#pragma mark -
#pragma mark Application lifecycle
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Our database name
databaseName = @"MPsqlitedb.sql";
// Get the document directory path and append databaes name to the path..
NSArray *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [docsPath objectAtIndex:0];
databasePath = [docDir stringByAppendingPathComponent:databaseName];
// Add the database into the path if it is already not exists.
[self CreateDatabaseIfRequired];
// Read the database and extract the contents..
[self ReadAndExtractDatabase];
// Override point for customization after app launch
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
-(void) CreateDatabaseIfRequired {
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL bAvailable = [fileManager fileExistsAtPath:databasePath];
// database already exists so just exit from here..
if ( bAvailable ) return;
// if not exists copy the db into the path..
NSString *databaseAtResourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
[fileManager copyItemAtPath:databaseAtResourcePath toPath:databasePath error:nil];
[fileManager release];
}
-(void) ReadAndExtractDatabase {
sqlite3 *database;
elements = [[NSMutableArray alloc] init];
// Open database
if ( sqlite3_open([databasePath UTF8String], &database) ==SQLITE_OK )
{
const char *sqlstatement = "select * from mysqlitetable";
sqlite3_stmt *combiledstatement;
printf( "could not prepare statemnt: %s\n", sqlite3_errmsg(database) );
if ( sqlite3_prepare_v2(database, sqlstatement, -1, &combiledstatement, NULL)==SQLITE_OK )
{
while ( sqlite3_step(combiledstatement)==SQLITE_ROW )
{
NSString *name = [NSString stringWithUTF8String:(char*) sqlite3_column_text(combiledstatement, 1)];
NSString *nationalAnthemDesc = [NSString stringWithUTF8String:(char*) sqlite3_column_text(combiledstatement, 2)];
NSString *image = [NSString stringWithUTF8String:(char*) sqlite3_column_text(combiledstatement,3)];
CountryDetails *detObj = [ [CountryDetails alloc]initDetails:name :nationalAnthemDesc :image ];
[elements addObject:detObj];
[detObj release];
}
}
// release the combiled statement
sqlite3_finalize(combiledstatement);
}
sqlite3_close(database);
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Save data if appropriate
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[navigationController release];
[window release];
[super dealloc];
}
// RootViewController.h file ########################################################
#import "DetailViewController.h"
@interface RootViewController : UITableViewController {
DetailViewController *detViewController;
}
@property (nonatomic, retain) DetailViewController *detViewController;
@end
// RootViewController.m file ########################################################
#import "RootViewController.h"
#import "MySQLLiteSampleAppDelegate.h"
#import "CountryDetails.h"
@implementation RootViewController
@synthesize detViewController;
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.title = @"Country details";
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release anything that can be recreated in viewDidLoad or on demand.
// e.g. self.myOutlet = nil;
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
MySQLLiteSampleAppDelegate *appDelegate = (MySQLLiteSampleAppDelegate*) [ [UIApplication sharedApplication] delegate];
return appDelegate.elements.count;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
MySQLLiteSampleAppDelegate *appDelegate = (MySQLLiteSampleAppDelegate*) [ [UIApplication sharedApplication] delegate ];
CountryDetails *contryDet = (CountryDetails*) [appDelegate.elements objectAtIndex:indexPath.row];
[cell setText:contryDet.countryname];
return cell;
}
// Override to support row selection in the table view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MySQLLiteSampleAppDelegate *myAppDelegate = (MySQLLiteSampleAppDelegate *) [ [UIApplication sharedApplication] delegate ];
CountryDetails *contryDet = (CountryDetails *) [myAppDelegate.elements objectAtIndex:indexPath.row];
// Navigation logic may go here -- for example, create and push another view controller.
detViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
[self.navigationController pushViewController:detViewController animated:YES];
detViewController.title = [contryDet countryname];
[detViewController.natAnthemDescView setText:[contryDet nationalanthem] ];
// download image from url
NSData *imgdata = [NSData dataWithContentsOfURL:[NSURL URLWithString:[contryDet cntryflagimg] ] ];
UIImage *flagImage = [ [UIImage alloc] initWithData:imgdata];
detViewController.flagImageView.contentMode = UIViewContentModeScaleAspectFit;
//detViewController.flagImageView.frame = CGRectMake(329, 460, 329, 186);
[detViewController.flagImageView setImage:flagImage ];
[detViewController release];
}
- (void)dealloc {
[super dealloc];
}
// CountryDetails.h file ########################################################
#import
@interface CountryDetails : NSObject {
NSString *countryname;
NSString *nationalanthem;
NSString *cntryflagimg;
}
@property (nonatomic, retain) NSString* countryname;
@property (nonatomic, retain) NSString* nationalanthem;
@property (nonatomic, retain) NSString* cntryflagimg;
-(id) initDetails : (NSString*) cntryname :(NSString*) natAnthDetail :(NSString*) flagImage;
// CountryDetails.m file ########################################################
#import "CountryDetails.h"
@implementation CountryDetails
@synthesize countryname;
@synthesize nationalanthem;
@synthesize cntryflagimg;
-(id) initDetails : (NSString*) cntryname :(NSString*) natAnthDetail :(NSString*) flagImage
{
self.countryname = cntryname;
self.nationalanthem = natAnthDetail;
self.cntryflagimg = flagImage;
return self;
}
@end
// DetailViewController.h file ########################################################
#import
@interface DetailViewController : UIViewController {
IBOutlet UITextView *natAnthemDescView;
IBOutlet UIImageView *flagImageView;
}
@property (nonatomic, retain) IBOutlet UITextView *natAnthemDescView;
@property (nonatomic, retain) IBOutlet UIImageView *flagImageView;
@end
// DetailViewController.m file ########################################################
#import "DetailViewController.h"
@implementation DetailViewController
@synthesize natAnthemDescView;
@synthesize flagImageView;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
Please drop your comments if it really helped you in someway....