iOS 使用 FMDB 進行本地數(shù)據(jù)儲存

DNFMDB.gif

一、主要思想

將整個數(shù)據(jù)模型 model 作為數(shù)據(jù)庫表中的一個鍵值來存儲(在創(chuàng)建表的SQLite語句中model的字段類型為 BLOB,這樣省去了根據(jù)model 的屬性一一對應創(chuàng)建數(shù)據(jù)庫字段)

二、FMDB 簡介

簡介:
FMDBiOS平臺的SQLite數(shù)據(jù)庫框架,FMDBOC的方式封裝了SQLiteC語言API

優(yōu)點:
使用起來更加面向對象,省去了很多麻煩、冗余的C語言代碼;對比蘋果自帶的Core Data框架,更加輕量級和靈活;提供了多線程安全的數(shù)據(jù)庫操作方法,有效地防止數(shù)據(jù)混亂

核心類:
FMDatabase:一個 FMDatabase對象就代表一個單獨的SQLite數(shù)據(jù)庫,用來執(zhí)行SQL語句
FMResultSet:使用FMDatabase查詢之后的結果集
FMDatabaseQueue:用于在多線程中執(zhí)行多個查詢或更新,它是線程安全的

三、具體步驟

(一)準備

創(chuàng)建Xcode 測試項目,將FMDB導入項目

(二)FMDB 封裝增刪改查

(1)創(chuàng)建工具類, 引入FMDB頭文件 #import <FMDB/FMDB.h>

屏幕快照 2019-03-11 17.07.27.png

(2)創(chuàng)建 NSObject的分類,添加@property (nonatomic, assign) UInt32 user_id; 屬性,使用runtime添加setget方法

@interface NSObject (Extra)

@property (nonatomic, assign) UInt32 user_id;

@end
@implementation NSObject (Extra)

static NSString *User_Id_Key = @"userIdKey";

- (void)setUser_id:(UInt32)user_id {
    
    objc_setAssociatedObject(self, &User_Id_Key, @(user_id), OBJC_ASSOCIATION_ASSIGN);
}

- (UInt32)user_id {
    
    NSNumber *num =  objc_getAssociatedObject(self, &User_Id_Key);
    return num.intValue;
}

@end

這里的user_id用來作為modelid,用來當做表數(shù)據(jù)中的主鍵,后面會通過這個id來進行數(shù)據(jù)庫的刪除和修改操作。由于user_id使用了UInt32類型,但是runtime不可以直接添加基本數(shù)據(jù)類型的屬性(會報錯),所以這里我就轉換成了對象
(3)封裝增刪改查方法
創(chuàng)建全局靜態(tài)的FMDatabase成員變量來進行數(shù)據(jù)庫操作
NSString類型的tableName用來存儲表的名稱(當創(chuàng)建多個表的時候,我的這種方法可能會出問題--->未驗證)

@interface DNFMDBTool ()
// 用來存儲數(shù)據(jù)庫表的名稱
@property (nonatomic, copy) NSString *tableName;
@end

static FMDatabase * _db;

創(chuàng)建打開數(shù)據(jù)庫
獲取沙盒路徑創(chuàng)建、打開數(shù)據(jù)庫

- (FMDatabase *)dn_openDatabase {
    
    NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSString * dbPath = [path stringByAppendingPathComponent:@"DNFMDBTools.sqlite"];
    
    _db = [FMDatabase databaseWithPath:dbPath];
    
    if ([_db open]) {
        DNLog(@"open dataBase sueccess");
    }
    return _db;
}

創(chuàng)建表
(這里將表的名字存儲為全局的變量,在創(chuàng)建多張表是可能會出問題)

/** 創(chuàng)建表 */
- (void)dn_createTable:(NSString *)tableName {
    
    self.tableName = tableName;
    
    [self dn_openDatabase];
    
    NSString *sql = [NSString stringWithFormat:@"create table if not exists %@(id integer primary key autoincrement, model BLOB)", self.tableName];
    BOOL result = [_db executeUpdate:sql];
    
    if (result) {
        DNLog(@"create table success");
    }
}

插入數(shù)據(jù)
這里將傳入的將要存儲的model歸檔為 NSData類型,對應存儲為數(shù)據(jù)庫表中的 BLOB類型

- (void)dn_insertData:(id)data {
    
    [self dn_openDatabase];
    
    NSData *modelData = [NSKeyedArchiver archivedDataWithRootObject:data];
    NSString *sql = [NSString stringWithFormat:@"insert into %@(model) values (?)", self.tableName];
    
    BOOL result = [_db executeUpdate:sql values:@[modelData] error:nil];
    
    if (result) {
        DNLog(@"insert data success");
    }
    [_db close];
}

刪除數(shù)據(jù)
這里將剛才我們在分類中添加的 user_id作為我們刪除數(shù)據(jù)的標識

- (void)dn_deleteDateUid:(UInt32)uid {
    
    [self dn_openDatabase];
    NSString *sql = [NSString stringWithFormat:@"delete from %@ where id = ?", self.tableName];
    BOOL result = [_db executeUpdate:sql values:@[@(uid)] error:nil];
    if (result) {
        
        DNLog(@"delete data success");
    }
    [_db close];
}

更新數(shù)據(jù)
這里將傳入進來的model歸檔為data類型,分類中添加的 user_id作為我們更新數(shù)據(jù)的標識

- (void)dn_updateData:(id)data uid:(UInt32)uid {
    
    [self dn_openDatabase];
    
    NSData *modelData = [NSKeyedArchiver archivedDataWithRootObject:data];
    NSString * sql = [NSString stringWithFormat:@"update %@ set model = ? where id = ?", self.tableName];
    BOOL result = [_db executeUpdate:sql values:@[modelData, @(uid)] error:nil];
    
    if (result) {
        DNLog(@"update data success");
    } else {
        
        [_db rollback];
    }
    [_db close];
}

查詢數(shù)據(jù)
利用 FMResultSet查詢數(shù)據(jù)庫得到的結果集,對應獲取數(shù)據(jù)庫中的主鍵id和存儲的數(shù)據(jù)類型model,并將 NSData 類型的modelData 反歸檔,并將對應的model模型放到數(shù)組中返回

- (NSMutableArray *)dn_selectAllData {
    
    [self dn_openDatabase];
    NSString *sql = [NSString stringWithFormat:@"select * from %@", self.tableName];
    FMResultSet *result = [_db executeQuery:sql];
    NSMutableArray *resultArr = [NSMutableArray array];
    while (result.next) {
        
        NSObject *model = [[NSObject alloc] init];
        // 獲取表中存儲字段對應的值
        NSData *modelData = [result dataForColumn:@"model"];
        UInt32 uid        = [result intForColumn:@"id"];
        
        model = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:modelData error:nil];
        model.user_id = uid;
        
        [resultArr addObject:model];
    }
    [_db close];
    return resultArr;
}

刪除表

- (void)dropTable {
    
    [self dn_openDatabase];
    NSString *sql = [NSString stringWithFormat:@"drop table if exists %@", self.tableName];
    BOOL result = [_db executeUpdate:sql withArgumentsInArray:@[]];
    if (result) {
        
        NSLog(@"drop table success");
    }
    [_db close];
}

以上就是我關于FMDB封裝的全部內容,歡迎各位大佬指正錯誤。Demo地址

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

友情鏈接更多精彩內容