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