美文网首页WKweb使用,FMDB讲解和封装
iOS 使用 FMDB 进行本地数据储存

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

作者: 写_Bug_小能手 | 来源:发表于2019-03-11 18:15 被阅读0次
    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地址

    相关文章

      网友评论

        本文标题:iOS 使用 FMDB 进行本地数据储存

        本文链接:https://www.haomeiwen.com/subject/hambpqtx.html