iOS FMDB 大數(shù)據(jù)處理

iOS中大量數(shù)據(jù)的存儲(chǔ),用的最多的是FMDB,小編在使用過(guò)程中遇到不少坑點(diǎn)。

一般情況下,數(shù)據(jù)庫(kù)實(shí)例需要單例,像這樣創(chuàng)建

static DBManager *_DB = nil;
+ (DBManager *)shareManager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (_DB == nil) {
            _DB = [[DBManager alloc] init];
        }
    });
    return _DB;
}
- (id)init{
    self = [super init];
    if (self) {
        NSString *path = [NSHomeDirectory() stringByAppendingString:@"/Documents/app.db"];
        _dateBase = [[FMDatabase alloc] initWithPath:path];
        if ([_dateBase open]) {
            NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)成功");
            NSString *sql = @"create table if not exists appa(applicationId varchar(32),name varchar(128),iconUrl varchar(1024))";
            if ([_dateBase executeUpdate:sql]) {
                NSLog(@"創(chuàng)建表格成功");
            }else{
                NSLog(@"創(chuàng)建表格失敗");
            }
        }else{
            NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)失敗");
        }
    }
    return self;
}

這樣,<code>_dataBase</code>可以調(diào)用<code> executeQuery:(NSString *), ...</code>方法,返回<code>FMResultSet</code>結(jié)果集對(duì)象;除查詢外的包括創(chuàng)建、刪除表,增刪改數(shù)據(jù),都可以調(diào)用<code>executeUpdate:(NSString *), ...</code>方法,返回<code>BOOL</code>值。

// 查詢SQL語(yǔ)句舉例
NSString *sql = [NSString stringWithFormat:@"SELECT * FROM tableName WHERE idstr > %@ ORDER BY idstr DESC LIMIT 20;", @"123"];
// 執(zhí)行SQL
FMResultSet *set = [_dataBase executeQuery:sql];
while (set.next) {
    // 獲取的數(shù)據(jù)
}
// 更新SQL語(yǔ)句舉例
NSString *sql = [CREATE TABLE IF NOT EXISTS tableName (id integer PRIMARY KEY, name varchar(32) NOT NULL, idstr text NOT NULL];
// 執(zhí)行SQL
BOOL isSuccess = [_dataBase executeUpdate:sql];
if (isSuccess) {
    // 成功
}

然而,這會(huì)卡主線程,瘋狂的向數(shù)據(jù)庫(kù)插入數(shù)據(jù),你會(huì)發(fā)現(xiàn)你的應(yīng)用卡死了,開(kāi)啟多線程貌似可以解決問(wèn)題,不一會(huì)兒數(shù)據(jù)庫(kù)文件將會(huì)損壞,控制臺(tái)也會(huì)打印錯(cuò)誤信息,<code>database is bad</code>,打開(kāi)數(shù)據(jù)庫(kù)存儲(chǔ)的路徑,會(huì)看到帶后綴的數(shù)據(jù)庫(kù)損壞文件

使用多線程沒(méi)有錯(cuò),數(shù)據(jù)庫(kù)文件的操作也需要線程安全,那么必須用到數(shù)據(jù)庫(kù)隊(duì)列<code>FMDatabaseQueue</code>,一般也是單例,調(diào)用方法<code>inDatabase:^(FMDatabase *db)block</code>或者<code>inTransaction:^(FMDatabase *db)block</code>,后者執(zhí)行效率高

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:MessageDBPath];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {

    NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (id integer PRIMARY KEY, msg_id text);",tableName];

    if ([db executeUpdate:sql]) {
         NSLog(@"創(chuàng)表成功或存在表");
    }else{
}];

開(kāi)啟事務(wù)后,顯得方便很多,不用手動(dòng)打開(kāi)數(shù)據(jù)庫(kù),它會(huì)自動(dòng)管理,把任務(wù)放在隊(duì)列中執(zhí)行,誰(shuí)也碰不到前面的腳,每個(gè)人都很幸福

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:MessageDBPath];
    [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (id integer PRIMARY KEY, msg_id text);",tableName];

        if ([db executeUpdate:sql]) {
            NSLog(@"創(chuàng)表成功或存在表");
        }else{
    }];
});

像這樣做,數(shù)據(jù)不會(huì)同步返回了,界面可以先放個(gè)菊花,待數(shù)據(jù)回調(diào)后,再主線程刷新UI,更多開(kāi)啟多線程的方法,可以參考我的另一篇博文 ios 使用多線程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容