iOS 使用 FMDB 进行本地数据储存

DNFMDB.gif

一、主要思想

将整个数据模型 model 作为数据库表中的一个键值来存储(在创建表的SQLite语句中model的字段类型为 BLOB,这样省去了根据model 的属性一一对应创建数据库字段)

二、FMDB 简介

简介:
FMDBiOS平台的SQLite数据库框架,FMDBOC的方式封装了SQLiteC语言API

优点:
使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码;对比苹果自带的Core Data框架,更加轻量级和灵活;提供了多线程安全的数据库操作方法,有效地防止数据混乱

核心类:
FMDatabase:一个 FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句
FMResultSet:使用FMDatabase查询之后的结果集
FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的

三、具体步骤

(一)准备

创建Xcode 测试项目,将FMDB导入项目

(二)FMDB 封装增删改查

(1)创建工具类, 引入FMDB头文件 #import <FMDB/FMDB.h>

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

(2)创建 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,用来当做表数据中的主键,后面会通过这个id来进行数据库的删除和修改操作。由于user_id使用了UInt32类型,但是runtime不可以直接添加基本数据类型的属性(会报错),所以这里我就转换成了对象
(3)封装增删改查方法
创建全局静态的FMDatabase成员变量来进行数据库操作
NSString类型的tableName用来存储表的名称(当创建多个表的时候,我的这种方法可能会出问题--->未验证)

@interface DNFMDBTool ()
// 用来存储数据库表的名称
@property (nonatomic, copy) NSString *tableName;
@end

static FMDatabase * _db;

创建打开数据库
获取沙盒路径创建、打开数据库

- (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;
}

创建表
(这里将表的名字存储为全局的变量,在创建多张表是可能会出问题)

/** 创建表 */
- (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");
    }
}

插入数据
这里将传入的将要存储的model归档为 NSData类型,对应存储为数据库表中的 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];
}

删除数据
这里将刚才我们在分类中添加的 user_id作为我们删除数据的标识

- (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];
}

更新数据
这里将传入进来的model归档为data类型,分类中添加的 user_id作为我们更新数据的标识

- (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];
}

查询数据
利用 FMResultSet查询数据库得到的结果集,对应获取数据库中的主键id和存储的数据类型model,并将 NSData 类型的modelData 反归档,并将对应的model模型放到数组中返回

- (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地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343