SQLite是一種小型的輕量級的關系型資料庫,在移動裝置上使用是非常好的選擇,無論是Android還是IOS,都内置了SQLite資料庫,現在的版本都是SQLite3。在IOS中使用SQLite如果使用SDK提供的方法,特别麻煩也不利于了解和使用,在之前的http://blog.csdn.net/tangren03/article/details/7781930文章中就是使用IOS的SDK自帶的SQLite API來使用資料庫,感覺使用很不友善,今天就講講一個針對IOS的SQlite API封裝的第三方庫FMDB,FMDB對SDK中的API做了一層封裝,使之使用OC來通路,使用友善而且更熟悉。FMDB的下載下傳位址https://github.com/ccgus/fmdb。
FMDB主要涉及兩個類,FMDatabase和FMResultSet,前者類似于Android中的SQLiteOpenHelper或SQLiteDatabase,FMResultSet類似于Android中的Cursor,用來存儲結果集。
下載下傳完FMDB源碼後把檔案拖到工程中,并導入SQLite支援庫,工程目錄如下:

然後就是這個Demo的完整截圖:
然後就來看看如何操作FMDB:
//點選按鈕後執行儲存到資料庫的操作
- (IBAction)saveButtonClicked:(id)sender {
//擷取Document檔案夾下的資料庫檔案,沒有則建立
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"user.db"];
//擷取資料庫并打開
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
if (![database open]) {
NSLog(@"Open database failed");
return;
}
//建立表(FMDB中隻有update和query操作,出了查詢其他都是update操作)
[database executeUpdate:@"create table user (name text,gender text,age integer)"];
//插入資料
BOOL insert = [database executeUpdate:@"insert into user values (?,?,?)",nameTextField.text,genderTextField.text,ageTextField.text];
if (insert) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"儲存成功" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
[database close];
}
操作成功後彈出提示框:
//點選按鈕後執行查詢操作
- (IBAction)queryButtonTapped:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
NSString *dbPath = [documentPath stringByAppendingPathComponent:@"user.db"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
if (![database open]) {
return;
}
//不需要像Android中那樣關閉Cursor關閉FMResultSet,因為相關的資料庫關閉時,FMResultSet也會被自動關閉
FMResultSet *resultSet = [database executeQuery:@"select * from user"];
while ([resultSet next]) {
NSString *name = [resultSet stringForColumn:@"name"];
NSString *gender = [resultSet stringForColumn:@"gender"];
int age = [resultSet intForColumn:@"age"];
NSLog(@"Name:%@,Gender:%@,Age:%d",name,gender,age);
}
[database close];
//這裡也不需要release
// [database release];
}
FMResultSet還支援以下方式擷取值:
-
intForColumn:
-
longForColumn:
-
longLongIntForColumn:
-
boolForColumn:
-
doubleForColumn:
-
stringForColumn:
-
dateForColumn:
-
dataForColumn:
-
dataNoCopyForColumn:
-
UTF8StringForColumnIndex:
-
objectForColumn:
//執行條件查詢操作
- (IBAction)queryByConditionBtnTapped:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex:0];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"user.db"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
if (![database open]) {
return;
}
FMResultSet *resultSet = [database executeQuery:@"select * from user where name = ?",@"Ryan"];
while ([resultSet next]) {
NSString *name = [resultSet stringForColumn:@"name"];
NSString *gender = [resultSet stringForColumn:@"gender"];
int age = [resultSet intForColumn:@"age"];
NSLog(@"Name:%@,Gender:%@,Age:%d",name,gender,age);
}
[database close];
}
//執行更新操作
- (IBAction)updateBtnTapped:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex:0];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"user.db"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
if (![database open]) {
return;
}
//參數必須是NSObject的子類,int,double,bool這種基本類型,需要封裝成對應的包裝類才可以
BOOL update = [database executeUpdate:@"update user set name = ? where age = ?",@"RyanTang",[NSNumber numberWithInt:24]];
if(update){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"更新成功" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
[database close];
}
//執行删除操作
- (IBAction)deleteBtnTapped:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex:0];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"user.db"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
if (![database open]) {
return;
}
BOOL delete = [database executeUpdate:@"delete from user where name = ?",@"Tang"];
if (delete) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"删除成功" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
[database close];
}
如果我們的app需要多線程操作資料庫,那麼就需要使用FMDatabaseQueue來保證線程安全了。切記不能在多個線程中共同一個FMDatabase對象并且在多個線程中同時使用,這個類本身不是線程安全的,這樣使用會造成資料混亂等問題。
使用FMDatabaseQueue很簡單,首先用一個資料庫檔案位址來初使化FMDatabaseQueue,然後就可以将一個閉包(block)傳入inDatabase方法中。在閉包中操作資料庫,而不直接參與FMDatabase的管理。
-(void)executeDBOperation
{
//擷取Document檔案夾下的資料庫檔案,沒有則建立
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dbPath = [docPath stringByAppendingPathComponent:@"user.db"];
FMDatabaseQueue *databaseQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
[databaseQueue inDatabase:^(FMDatabase *db){
[db executeUpdate:@"insert into user values (?,?,?)",@"Ren",@"Male",[NSNumber numberWithInt:20]];
}];
[databaseQueue close];
}
工程源碼:下載下傳
加入我們的QQ群或微信公衆賬号請檢視: Ryan's zone公衆賬号及QQ群
歡迎關注我的新浪微網誌和我交流:@唐韌_Ryan