FMDB是以OC的方式封裝了SQLite的C語言API,使用起來更加面向對象,省去了不少麻煩、冗餘的C語言代碼;對比蘋果自帶的Core Data框架,更加輕量級和靈活;提供了多線程安全的數據庫操做方法,有效地防止數據混亂;FMDB同時兼容ARC和非ARC工程,在編譯的時候會自動根據工程配置來調整相關的內存管理代碼。html
FMDB有三個主要的類sql
經過指定SQLite數據庫文件路徑來建立FMDatabase對象數據庫
FMDatabase *db = [FMDatabase databaseWithPath:path]; if (![db open]) { NSLog(@"數據庫打開失敗!"); }
建立FMDatabase對象時參數爲SQLite數據庫文件路徑。該路徑能夠是如下三種之一:json
一、具體文件路徑數組
二、空字符串@""安全
三、NULLruby
在和數據庫交互 以前,數據庫必須是打開的。若是資源或權限不足沒法打開或建立數據庫,都會致使打開失敗,返回BOOL類型多線程
if (![db open]) { [db release]; return; }
使用executeUpdate:方法執行更新app
- (BOOL)executeUpdate:(NSString*)sql, ... - (BOOL)executeUpdateWithFormat:(NSString*)format, ... - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
示例框架
[db executeUpdate:@"UPDATE t_student SET age = ? WHERE name = ?;", @20, @"Jack"]
SELECT命令就是查詢,執行查詢的方法是以 -excuteQuery開頭的。
查詢方法
- (FMResultSet *)executeQuery:(NSString*)sql, ... - (FMResultSet *)executeQueryWithFormat:(NSString*)format, ... - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
執行查詢時,若是成功返回FMResultSet對象, 錯誤返回nil. 與執行更新至關,支持使用 NSError**參數。同時,你也能夠使用 -lastErrorCode和-lastErrorMessage獲知錯誤信息。
爲了遍歷查詢結果,你能夠使用while循環。你還須要知道怎麼跳到下一個記錄。使用FMDB,很簡單實現,就像這樣:
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"]; while ([s next]) { //retrieve values for each record }
你必須一直調用 -[FMResultSet next] 在你訪問查詢返回值以前,甚至你只想要一個記錄:
FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"]; if ([s next]) { int totalCount = [s intForColumnIndex:0]; }
FMResultSet 提供了不少方法來得到所需的格式的值:
intForColumn:
longForColumn:
longLongIntForColumn:
boolForColumn:
doubleForColumn:
stringForColumn:
dataForColumn:
dataNoCopyForColumn:
UTF8StringForColumnIndex:
objectForColumn:
這些方法也都包括 {type}ForColumnIndex 的這樣子的方法,參數是查詢結果集的列的索引位置。
你無需調用 [FMResultSet close]來關閉結果集, 當新的結果集產生,或者其數據庫關閉時,會自動關閉。
當使用完數據庫,你應該 -close 來關閉數據庫鏈接來釋放SQLite使用的資源。
[db close];
在多個線程中同時使用一個FMDatabase實例是不明智的。如今你能夠爲每一個線程建立一個FMDatabase對象。 不要讓多個線程分享同一個實例,它沒法在多個線程中同時使用。 若此,壞事會常常發生,程序會時不時崩潰,或者報告異常,或者隕石會從天空中掉下來砸到你Mac Pro. 總之很崩潰。因此,不要初始化FMDatabase對象,而後在多個線程中使用。請使用 FMDatabaseQueue,它是你的朋友並且會幫助你。如下是使用方法:
首先建立隊列
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
這樣使用
[queue inDatabase:^(FMDatabase *db) { [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; FMResultSet *rs = [db executeQuery:@"select * from foo"]; while([rs next]) { … } }];
像這樣,輕鬆地把簡單任務包裝到事務裏
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) { [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; if (whoopsSomethingWrongHappened) { *rollback = YES; return; } // etc… [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; }];
FMDatabaseQueue將運行在一個序列化隊列塊。因此若是你從多個線程在同一時間調用FMDatabaseQueue的方法,他們將執行他們收到的指令。這樣查詢和更新不會相互影響,每個都是快樂的。
FMDBDataBase.h
// FMDBDataBase.h #import <Foundation/Foundation.h> @interface FMDBDataBase : NSObject // 獲取數據庫管理對象單例的方法 + (FMDBDataBase *)sharedDataBase; // 關閉數據庫 - (void)closeDataBase; // 清空數據庫 - (BOOL)deleteDataBase; // 向搜索記錄表中插入新紀錄 - (BOOL)insertSearchText:(NSString *)searchText; // 查詢數據庫中是否包含當前搜索記錄 - (BOOL)isExistSearchText:(NSString *)searchText; // 獲取全部搜素記錄 - (NSMutableArray *)getAllSearchText; // 刪除全部搜索記錄 - (BOOL)deleteAllSearchText; @end
FMDBDataBase.m
#import "FMDBDataBase.h" #import "FMDB.h" @interface FMDBDataBase () @property (nonatomic, strong) FMDatabase *fmDataBase; @end @implementation FMDBDataBase + (FMDBDataBase *)sharedDataBase { static FMDBDataBase *fmdbDataBase = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ fmdbDataBase = [[FMDBDataBase alloc] init]; }); return fmdbDataBase; } - (instancetype)init { if (self = [super init]) { _fmDataBase = [FMDatabase databaseWithPath:[self getDataBasePath]]; // 若是數據庫打開失敗返回空值 if (![_fmDataBase open]) { return nil; } } // 若是數據庫打開成功 建立表 // 建立搜索歷史記錄表 NSString *searchHistorySql = @"CREATE TABLE IF NOT EXISTS t_history(t_id integer PRIMARY KEY AUTOINCREMENT, searchText text NOT NULL, age integer NOT NULL)"; BOOL isSuc = [_fmDataBase executeUpdate:searchHistorySql]; if (isSuc) { NSLog(@"建立成功!"); } return self; } - (NSString *)getDataBasePath { // 1.得到數據庫文件的路徑 NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; // NSString *doc = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; NSString *fileName = [doc stringByAppendingPathComponent:@"fmdb.sqlite"]; return fileName; } // 清空數據庫 - (BOOL)deleteDataBase { NSString *sql = @"DELETE FROM t_history"; BOOL isSuc = [_fmDataBase executeUpdate:sql]; if (isSuc) { NSLog(@"刪除成功"); return YES; } NSLog(@"刪除失敗"); return NO; } // 關閉數據庫 - (void)closeDataBase { if (_fmDataBase) { [_fmDataBase close]; } } // 查詢數據庫中是否包含當前搜索記錄 - (BOOL)isExistSearchText:(NSString *)searchText { NSString *sql = @"SELECT * FROM t_history"; FMResultSet *results = [_fmDataBase executeQuery:sql]; while (results.next) { if ([searchText isEqualToString:[results stringForColumn:@"searchText"]]) { return YES; } } return NO; } // 搜索記錄表中插入新記錄 - (BOOL)insertSearchText:(NSString *)searchText { if (!searchText || [searchText isEqualToString:@""] || [self isExistSearchText:searchText]) { NSLog(@"數據爲空或已存在"); return NO; } NSString *sql = @"INSERT INTO t_history(searchText) VALUES (?)"; // executeUpdate : 不肯定的參數用?來佔位 BOOL isInsertSuc = [_fmDataBase executeUpdate:sql, searchText]; if (isInsertSuc) { NSLog(@"%@插入成功", searchText); return YES; } NSLog(@"%@插入失敗", searchText); return NO; } // 獲取全部的搜索記錄 - (NSMutableArray *)getAllSearchText { NSString *sql = @"SELECT * FROM t_history order by t_id desc"; // 保存全部數據的數組 NSMutableArray *searchTests = [NSMutableArray array]; FMResultSet *results = [_fmDataBase executeQuery:sql]; while (results.next) { NSString *result = [results stringForColumn:@"searchText"]; [searchTests addObject:result]; } return searchTests; } // 刪除全部的搜索記錄 - (BOOL)deleteAllSearchText { NSString *sql = @"DELETE FROM t_history"; BOOL isDeleteSuc = [_fmDataBase executeUpdate:sql]; if (isDeleteSuc) { NSLog(@"刪除成功"); return YES; } return NO; } @end
iOS-Ant-Bang互助社區 426981364iOS技術交流羣 461069757 歡迎加入!