? ? 對于新手來說,iOS中使用的數據庫框架,fmdb無疑是較為簡單方便的。在我接觸fmdb前,查閱了很多資料,發現網上的demo參差不齊,有些過于基礎,項目中使用需要進一步封裝。因此,我針對項目中的時候,參考別人的demo,自己改進并寫了個封裝。希望對大家使用fmdb有幫助。如果有錯誤的地方,希望多多指正,謝謝。此篇文章緊對剛學習fmdb的新人提供參考,大神請忽略。iOS開發群143898492,歡迎有興趣的加入。
FMDB封裝的工具
這是封裝的工具類JHFMDBManager.h文件
#import <Foundation/Foundation.h>
#import"FMDB.h"
typedefvoid(^JHDBBlock)(FMDatabase*jh_db);
@interfaceJHFMDBManager :NSObject
+(instancetype)sharedInstance;
/**
*數據庫操作
*
*@param block操作block回調
*/
- (void)SQLHandler:(JHDBBlock)block;
@end
這是JHFMDBManager.m文件,FMDatabaseQueue是多線程安全的,這個使用時需要注意,多線程操作數據時,必須保證FMDatabaseQueue是同一個對象,否則會導致數據正在被操作時被鎖住的情況,導致操作失敗。這里用了懶加載,只new一個對象。(由于排版的原因導致下面的代碼分割開了,下面的代碼應是連在一塊的)。一般項目中只生成一個數據庫,數據庫里面多張表,保存不同對象數據。這里封裝的- (void)SQLHandler:(JHDBBlock)block方法,是調用sql語句的block。如何使用請看下文。
#import"JHFMDBManager.h"
@interfaceJHFMDBManager()
@property(nonatomic,strong)FMDatabaseQueue* queue;
@end
@implementationJHFMDBManager
+ (instancetype)sharedInstance
{
static JHFMDBManager*sharedInstance =nil;
static dispatch_once_tonceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [selfnew];
});
returnsharedInstance;
}
//獲取路徑
+ (NSString*)dbPathWithDirectoryName:(NSString*)directoryName DataBaseName:(NSString*)dbname
{
NSString*docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)lastObject];
NSFileManager*filemanage = [NSFileManagerdefaultManager];
if(directoryName ==nil|| directoryName.length==0) {
docsPath = [docsPath stringByAppendingPathComponent:@"jhOnesmile"];
}else{
docsPath = [docsPath stringByAppendingPathComponent:directoryName];
}
BOOLisDir;
BOOLexit =[filemanage fileExistsAtPath:docsPathisDirectory:&isDir];
if(!exit || !isDir) {
[filemanage createDirectoryAtPath:docsPathwithIntermediateDirectories:YESattributes:nilerror:nil];
}
NSString*dbpath = [docsPathstringByAppendingPathComponent:dbname];
NSLog(@"---------%@", dbpath);
returndbpath;
}
- (void)SQLHandler:(JHDBBlock)block
{
//線程安全,可以用多線程操作
[self.queue inDatabase:^(FMDatabase*db) {
if([db open]) {
@try{
//成功回調
block(db);
}
@catch(NSException *exception) {
//處理異常,也可以直接拋出,這樣調用者就能捕獲到異常信息
NSLog(@"處理異常,異常信息: %@", exception);
}
@finally{
[dbclose];//如果[db open]就要保證能關閉
}
}else{
NSLog(@"數據庫打開失敗,錯誤提示:%@", [db lastError]);
}
db =nil;
}];
}
/**
*創建數據庫多線程管理工具,必須是一個對象,否則會導致多線程使用中,出現操作失敗的現象
*(兩個操作同時操作一個數據庫會出現程序鎖,導致操作失敗)
*
*@return
*/
-(FMDatabaseQueue*)queue{
if(_queue==nil) {
//只創建一個數據庫,文件夾叫onesmile,數據庫文件名字onesmile.sqlite,表名稱根據創建的表來確定
NSString*dbName =@"onesmile.sqlite";
NSString*fileName =@"onesmile";
NSString*dbPath = [[self class]dbPathWithDirectoryName:fileNameDataBaseName:dbName];
_queue= [FMDatabaseQueue databaseQueueWithPath:dbPath];
}
return_queue;
}
自定義FMDB工具類的使用
我們有一個學生類,類屬性如下。那么我們該如何將這個類的對象保存到數據庫中呢?對于很多新手來說,希望省事點,能直接將對象保存到數據庫,然而這是無法做到的。比如某個班級,有60個學生,我們應先建立一個學生表,表里面的列便是學生類的屬性(正如項目中需要保存很多條新聞數據,或者是聊天數據等,那么新聞是一個模型,很多條新聞便是很多個對象,模型的屬性我們便可以保存為新聞表的列)(這里有點啰嗦,只是解釋給新手看的,高手略過)。
@interfaceJHUserModel :NSObject
/**用戶名*/
@property(nonatomic,copy)NSString*name;
/**用戶地*/
@property(nonatomic,copy)NSString*address;
/**用戶年齡*/
@property(nonatomic,copy)NSString*age;
@end
1.創建學生類表
我們在需要保存數據的控制器里,先創建該學生類student的表。createSqlStr是保存sql語句,這里的sql語句的意思很明顯,如果沒有student這個表,則創建,并且列為id,name,address,age,id是主鍵,其他列都保存為text類型,且不為空(如果可以為空對應的列則not null去掉即可)。關于更深層次的sql語句的學習,推薦去w3c官網學習,畢竟不會sql語句,用起fmdb會感到很吃力。創建代碼如下:
//創建表
[[JHFMDBManager sharedInstance]SQLHandler:^(FMDatabase*jh_db) {
NSString*createSqlStr =@"create table if not exists student (id integer primary key, name text not null,address text not null,age text not null)";
BOOL res = [jh_db executeUpdate:createSqlStr];
if(!res) {
NSLog(@"創建表出錯");
}else{
NSLog(@"創建表成功");
}
}];
2.查詢表
這里的set是查詢返回的FMResultSet對象,使用while循環遍歷所有查詢到的結果,在遍歷內獲取你想要的列即可。實際應用中,有可能需要排序,翻頁查詢,某個列的查詢最大最小值的那條數據等等,這就涉及到sql語句的應用了,具體可查詢相關資料,只要寫出該sql語句即可用如下的方式運行
//查詢數據
[[JHFMDBManager sharedInstance]SQLHandler:^(FMDatabase*jh_db) {
NSString*sqlString =@"select *from student";
FMResultSet*set = [jh_db executeQuery:sqlString];
while([set next]) {
NSString*name = [set stringForColumn:@"name"];
NSString*address = [set stringForColumn:@"address"];
NSString*age = [set stringForColumn:@"age"];
NSLog(@"用戶姓名:%@,地址:%@,年齡:%@",name,address,age);
}
}];
3.插入數據
//插入數據
[[JHFMDBManager sharedInstance] SQLHandler:^(FMDatabase *jh_db) {
NSString *sqlString =@"insert into student (name,address,age) values(?,?,?)";
BOOL res = [jh_db executeUpdate:sqlString,student.name,student.address,[NSString stringWithFormat:@"%d",16]];
if(!res) {
NSLog(@"插入出錯");
}else{
NSLog(@"插入成功");
}
}];
4.更新數據
某條數據變動了,則使用更新方法。
//更新數據
[[JHFMDBManager sharedInstance] SQLHandler:^(FMDatabase *jh_db) {
NSString *sqlString =@"update student set address = ? where age = ?";
BOOLres = [jh_db executeUpdate:sqlString,@"gfds",student.age];
if(!res) {
NSLog(@"更新出錯");
}else{
NSLog(@"更新成功");
}
}];
5.刪除數據
刪除數據需謹慎使用,一定要添加條件進行刪除,否則容易鬧出將整表甚至整個數據庫刪除的烏龍,需謹慎使用!
//刪除數據
[[JHFMDBManager sharedInstance] SQLHandler:^(FMDatabase *jh_db) {
NSString *sqlString =@"delete from userModel where name = ?";
BOOLres = [jh_db executeUpdate:sqlString,userModel.name];
if(!res) {
NSLog(@"刪除出錯");
}else{
NSLog(@"刪除成功");
}
}];
以上所有的操作都可以在子線程中執行,因為使用了FMDatabaseQueue,所以是線程安全的。很多不會用數據庫的新人,都是對sql語句不熟悉導致的。因此建議使用fmdb的時候,電腦裝個數據庫查看軟件,可以查看你對數據庫進行的操作,否則你進行了數據操作,根本不知道數據庫在背后到底如何做了什么。新人推薦使用SQLite Professional,想更深去學習sql,可以裝個mysql環境,Mysql是免費的,可以使用它自帶的MYSQLWorkbench管理工具查看數據庫的操作。對于大神來說略過。
我是iOS菜鳥onesmile 一笑,剛開始寫簡書,希望各位多多指教。歡迎到iOS開發群143898492交流,群較小,但探討問題較活躍。只要有問題都可以在里面,提問。懂的都會盡力解答。