What we will learn?
This tutorial will show you the basic of database programming on IPhone . We are going to use FMDatabase wrapper which simplifies the use of sqlite library. using FMDatabase we are going to create a program which populates a table with the database information and when a table cell is clicked the program will display additional information extracted from the database.
Things we will cover in this tutorial
We are going to learn the following thing:
-start a new project and add things we need to add database to our project
-learn a bit about FMDatabase and the functions available for us.
-extract information from the database
Source code for the project:
lets begin:
1. download the following files:
You downloaded here the wrapper functions for sqlite and the database we will use for the tutorial.
I'm not gonna show you in this tutorial how to create the database and if you want to create your own database u can find information on the subject in the following site:
Our database consists of 3 columns the first one is the primary key which is a unique index for every row in the database. the second one is a string of names of students, and the third ont is integer for the students id's.
the first column name is: 'pk', the second column name is: 'name' the third: 'id'
2. launch XCode
3. start a new project
4. choose navigation based application and name it:'database1'
5. right click classes in the groups and files and choose add -> new group
6. name the group database and copy the FMDatabase files to the new folder you just created
make sure you check the check box that says copy the files...(if needed)
7. copy students7.sqlite to the resource
make sure you check the check box that says copy the files...(if needed)
right click frameworks in the groups and files choose add->existing frameworks
choose libsqlite3.0.dylib from the list and press add. if you cant find it you need to manually find it so press add other goto developer/platforms/iphoneos.platform/developer/SDKs/iPhoneOS3.2sdk/usr/lib
and choose the file i mentioned earlier.
next we will create the openning window
8. right click classes choose add new files
9. choose UIViewController subclass and make sure only 'with xib...' check box is selected
10. name the class: OpenWinViewController
11. move the xib file that was created to the resources group
change the OpenWinViewController.h to look like this:
//
// OpenWinViewController.h
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import
@interface OpenWinViewController : UIViewController {
}
-(IBAction)btnNamesClick:(id)sender;
@end
// OpenWinViewController.h
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import
@interface OpenWinViewController : UIViewController {
}
-(IBAction)btnNamesClick:(id)sender;
@end
12. change the OpenWinViewController.m to look like this:
//
// OpenWinViewController.m
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import "OpenWinViewController.h"
#import "RootViewController.h"
@implementation OpenWinViewController
-(IBAction)btnNamesClick:(id)sender{
RootViewController* viewController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
- (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 {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
// OpenWinViewController.m
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import "OpenWinViewController.h"
#import "RootViewController.h"
@implementation OpenWinViewController
-(IBAction)btnNamesClick:(id)sender{
RootViewController* viewController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
- (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 {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
13. double click the OpenWinViewController.xib file that was created and drag a button
and connect the touch up inside event to btnNamesClick event
14. now double click MainWindow.xib and change the navigation controller child to be the new class we just created and the nib to be the nib we created.
we will now create the NSObject that will correspond to a row in the database
15. right click classes and choose add->new file
16. choose here objective c class and make sure u select subclass of nsobject.
17. name the classes: 'singleStudent'
18. change the singleStudent.h to look like this:
//
// singleStudent.h
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import
@interface singleStudent : NSObject {
int studentId;
int pk;
NSString* strName;
}
@property (nonatomic,assign)int studentId;
@property (nonatomic,assign)int pk;
@property (nonatomic,retain) NSString* strName;
-(id)initWithData:(int)intPk :(NSString *)name :(int)aId;
@end
// singleStudent.h
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import
@interface singleStudent : NSObject {
int studentId;
int pk;
NSString* strName;
}
@property (nonatomic,assign)int studentId;
@property (nonatomic,assign)int pk;
@property (nonatomic,retain) NSString* strName;
-(id)initWithData:(int)intPk :(NSString *)name :(int)aId;
@end
19. change the singleStudent.m to look like this:
//
// singleStudent.m
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import "singleStudent.h"
@implementation singleStudent
@synthesize studentId,pk,strName;
-(id)initWithData:(int)intPk :(NSString *)name :(int)aId{
self.studentId = aId;
self.strName = name;
self.pk = intPk;
return self;
}
@end
// singleStudent.m
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import "singleStudent.h"
@implementation singleStudent
@synthesize studentId,pk,strName;
-(id)initWithData:(int)intPk :(NSString *)name :(int)aId{
self.studentId = aId;
self.strName = name;
self.pk = intPk;
return self;
}
@end
20. change the database1appdelegate.h to look like this:
//
// database1AppDelegate.h
// database1
//
// Created by Yariv Katz on 10/25/10.
// Copyright YKSoftware 2010. All rights reserved.
//
#import
#import "FMDatabase.h"
@interface database1AppDelegate : NSObject{
UIWindow *window;
UINavigationController *navigationController;
NSMutableArray* aryDatabase;
NSString* databaseName;
NSString* databasePath;
FMDatabase* db;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic,retain) NSMutableArray* aryDatabase;
@end
// database1AppDelegate.h
// database1
//
// Created by Yariv Katz on 10/25/10.
// Copyright YKSoftware 2010. All rights reserved.
//
#import
#import "FMDatabase.h"
@interface database1AppDelegate : NSObject
UIWindow *window;
UINavigationController *navigationController;
NSMutableArray* aryDatabase;
NSString* databaseName;
NSString* databasePath;
FMDatabase* db;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic,retain) NSMutableArray* aryDatabase;
@end
21. change the database1appdelegate.m to look like this
change this function:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the navigation controller's view to the window and display.
[self updateNames];
[self checkAndCreateDatabase];
[self readWordsFromDatabase];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
// Override point for customization after application launch.
// Add the navigation controller's view to the window and display.
[self updateNames];
[self checkAndCreateDatabase];
[self readWordsFromDatabase];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
add these three new function to database1appdelegate.m:
-(void)updateNames{
databaseName = @"students7.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
}
-(void) checkAndCreateDatabase{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:databasePath];
if(success) return;
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
[fileManager release];
}
-(void) readWordsFromDatabase {
[self updateNames];
db = [FMDatabase databaseWithPath:databasePath];
aryDatabase = [[NSMutableArray alloc] init];
[db setLogsErrors:TRUE];
[db setTraceExecution:TRUE];
if (![db open]) {
NSLog(@"Could not open db.");
return;
}else {
NSLog(@"oooooooohooo. DB Open....");
}
FMResultSet *rs = [db executeQuery:@"select * from student"];
while ([rs next]) {
int aID = [rs intForColumn:@"id"];
int intPk=[rs intForColumn:@"pk"];
NSString* aName = [rs stringForColumn:@"name"];
NSLog(@"%s",aName);
singleStudent* sStudent = [[singleStudent alloc] initWithData:intPk :aName :aID];
[aryDatabase addObject:sStudent];
[sStudent release];
}
[db close];
}
databaseName = @"students7.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
}
-(void) checkAndCreateDatabase{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:databasePath];
if(success) return;
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
[fileManager release];
}
-(void) readWordsFromDatabase {
[self updateNames];
db = [FMDatabase databaseWithPath:databasePath];
aryDatabase = [[NSMutableArray alloc] init];
[db setLogsErrors:TRUE];
[db setTraceExecution:TRUE];
if (![db open]) {
NSLog(@"Could not open db.");
return;
}else {
NSLog(@"oooooooohooo. DB Open....");
}
FMResultSet *rs = [db executeQuery:@"select * from student"];
while ([rs next]) {
int aID = [rs intForColumn:@"id"];
int intPk=[rs intForColumn:@"pk"];
NSString* aName = [rs stringForColumn:@"name"];
NSLog(@"%s",aName);
singleStudent* sStudent = [[singleStudent alloc] initWithData:intPk :aName :aID];
[aryDatabase addObject:sStudent];
[sStudent release];
}
[db close];
}
add also the following imports:
#import "database1AppDelegate.h"
#import "RootViewController.h"
#import "singleStudent.h"
#import "RootViewController.h"
#import "singleStudent.h"
further explanation about the code we added you can find on the video
22. goto RootViewController.m and change the following function to look like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
database1AppDelegate *appDelegate = (database1AppDelegate *)[[UIApplication sharedApplication] delegate];
return [appDelegate.aryDatabase count];
}
database1AppDelegate *appDelegate = (database1AppDelegate *)[[UIApplication sharedApplication] delegate];
return [appDelegate.aryDatabase count];
}
23. change in the same file the following function:
- (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];
}
database1AppDelegate *appDelegate = (database1AppDelegate *)[[UIApplication sharedApplication] delegate];
singleStudent* sStudent =(singleStudent *) [appDelegate.aryDatabase objectAtIndex:indexPath.row];
cell.textLabel.text = [sStudent strName];
return cell;
}
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
database1AppDelegate *appDelegate = (database1AppDelegate *)[[UIApplication sharedApplication] delegate];
singleStudent* sStudent =(singleStudent *) [appDelegate.aryDatabase objectAtIndex:indexPath.row];
cell.textLabel.text = [sStudent strName];
return cell;
}
24. change the foolowing function in the same file to look like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
StudentViewController* viewController = [[StudentViewController alloc] initWithNibName:@"StudentViewController" bundle:nil];
self.title =@"Names";
database1AppDelegate *appDelegate = (database1AppDelegate *)[[UIApplication sharedApplication] delegate];
singleStudent* sStudent = [appDelegate.aryDatabase objectAtIndex:indexPath.row];
[self.navigationController pushViewController:viewController animated:YES];
[viewController.lblName setText:[sStudent strName]];
[viewController.lblID setText:[NSString stringWithFormat:@"%i",[sStudent studentId]]];
[viewController release];
}
StudentViewController* viewController = [[StudentViewController alloc] initWithNibName:@"StudentViewController" bundle:nil];
self.title =@"Names";
database1AppDelegate *appDelegate = (database1AppDelegate *)[[UIApplication sharedApplication] delegate];
singleStudent* sStudent = [appDelegate.aryDatabase objectAtIndex:indexPath.row];
[self.navigationController pushViewController:viewController animated:YES];
[viewController.lblName setText:[sStudent strName]];
[viewController.lblID setText:[NSString stringWithFormat:@"%i",[sStudent studentId]]];
[viewController release];
}
25. add the following imports to the same file above:
#import "RootViewController.h"
#import "database1AppDelegate.h"
#import "singleStudent.h"
#import "StudentViewController.h"
#import "database1AppDelegate.h"
#import "singleStudent.h"
#import "StudentViewController.h"
26. right click classes choose add new file and choose UIViewController subclass and make sure only the xib add xib check box is marked
27. name the new class: 'StudentViewController'
28 change the StudentViewController.h to look like this:
//
// StudentViewController.h
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import
@interface StudentViewController : UIViewController {
UILabel* lblName;
UILabel* lblID;
}
@property(nonatomic,retain)IBOutlet UILabel* lblName;
@property(nonatomic,retain)IBOutlet UILabel* lblID;
@end
// StudentViewController.h
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import
@interface StudentViewController : UIViewController {
UILabel* lblName;
UILabel* lblID;
}
@property(nonatomic,retain)IBOutlet UILabel* lblName;
@property(nonatomic,retain)IBOutlet UILabel* lblID;
@end
29. change the StudentViewController.m to look like this:
//
// StudentViewController.m
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import "StudentViewController.h"
@implementation StudentViewController
@synthesize lblName,lblID;
- (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 {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
// StudentViewController.m
// database1
//
// Created by Yariv Katz on 10/26/10.
// Copyright 2010 YKSoftware. All rights reserved.
//
#import "StudentViewController.h"
@implementation StudentViewController
@synthesize lblName,lblID;
- (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 {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
30. double click the StudentViewController.xib and add two labels connect the upper one to lblname and the lower one to lblID.
all done you can launch and play with your new program.
for full source code:
Hey,
ReplyDeleteYour link does not work for the full source good and also not for the FMdatabase,
I really like your tutorial so i want to make it, but do i really need to have the FMdatabase to complete this tutorial?
Robi
Hi Robi try right clicking the link and choose download link
ReplyDeletethis works for me.
cheers
It doesnt work, can forward the zip to my by email,
ReplyDeleter.urban@kobelcowelding.nl
Sample not not Working! I only see a black screen!
ReplyDeleteA great tutorial ywarezk, but as Robi says the link does not work. Could you also forward the zip to my email chrissy [at] xs4all [dot] nl Cheers and thanks!
ReplyDeleteI have a question about increasing the value added UISearch in a manner which is to be. Working together.
ReplyDeletePlz Plz guys forward the full source code and fmdaabase zip to me too!!!! anybody plz....my job is at stake.. i wil be fired if i cant do this.. i m working on a smilar project .... my id is mushtaque87@gmail.com
ReplyDeleteCan someone please forward me a copy of source code please.
ReplyDeletejimmy88.ie@gmail.com
Thanks for this tutorial. It's great overall, but I noticed a couple of issues with the text on this page:
ReplyDelete1. You have a few instances of #import by itself on a line, because the angle brackets aren't html-encoded.
2. In the steps, you never mention creating the StudentInfoViewController class. It's in the video, but not in the text.
Please forward me a copy of source code please.
ReplyDeletemikekam88@hotmail.com
This comment has been removed by the author.
ReplyDeleteSame here can someone send me a copy of FMDatabase.zip
ReplyDeletestudents7.sqlite
please~
chen_910701@hotmail.com
The Full Source Code isnt working, xcode gives me like 30 errors, please help!
ReplyDeletebut its working on my ipod without errors.... It it possible to add database files within the app???
ReplyDeleteSame here can someone send me a copy of FMDatabase.zip
ReplyDeletestudents7.sqlite
please~
ram.agrawal0786@gmail.com
i need the source code of this tutorial , please send it to my email
ReplyDeleterahman231@gmail.com
many thanks.
hi.
ReplyDeleteI'VE TRIED TO RUN THIS THING BUT THE SCREEN WAS BLACK...
CAN SOMEBODY HELP ME PLEASE....
Hey. its absolutely working fine. You should update it with insert,update and delete queries.
ReplyDeletecan I please get the source code? dale.magnin@gmail.com
ReplyDeletei need the source code and the fmdatabase too please thanks much
ReplyDeletewhere can I download the source code?
ReplyDeleteA complete solution and deep info about iphone programming .
ReplyDeleteDevelopment is as much about the workflow as much as it is about the code. and its cool to start learning iphone through this way.
learning PHP through this way.
iphone developers