iOS FMDB 大数据处理

iOS中大量数据的存储,用的最多的是FMDB,小编在使用过程中遇到不少坑点。

一般情况下,数据库实例需要单例,像这样创建

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(@"打开数据库成功");
            NSString *sql = @"create table if not exists appa(applicationId varchar(32),name varchar(128),iconUrl varchar(1024))";
            if ([_dateBase executeUpdate:sql]) {
                NSLog(@"创建表格成功");
            }else{
                NSLog(@"创建表格失败");
            }
        }else{
            NSLog(@"打开数据库失败");
        }
    }
    return self;
}

这样,_dataBase可以调用 executeQuery:(NSString *), ...方法,返回FMResultSet结果集对象;除查询外的包括创建、删除表,增删改数据,都可以调用executeUpdate:(NSString *), ...方法,返回BOOL值。

// 查询SQL语句举例
NSString *sql = [NSString stringWithFormat:@"SELECT * FROM tableName WHERE idstr > %@ ORDER BY idstr DESC LIMIT 20;", @"123"];
// 执行SQL
FMResultSet *set = [_dataBase executeQuery:sql];
while (set.next) {
    // 获取的数据
}
// 更新SQL语句举例
NSString *sql = [CREATE TABLE IF NOT EXISTS tableName (id integer PRIMARY KEY, name varchar(32) NOT NULL, idstr text NOT NULL];
// 执行SQL
BOOL isSuccess = [_dataBase executeUpdate:sql];
if (isSuccess) {
    // 成功
}

然而,这会卡主线程,疯狂的向数据库插入数据,你会发现你的应用卡死了,开启多线程貌似可以解决问题,不一会儿数据库文件将会损坏,控制台也会打印错误信息,database is bad,打开数据库存储的路径,会看到带后缀的数据库损坏文件

使用多线程没有错,数据库文件的操作也需要线程安全,那么必须用到数据库队列FMDatabaseQueue,一般也是单例,调用方法inDatabase:^(FMDatabase *db)block或者inTransaction:^(FMDatabase *db)block,后者执行效率高

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(@"创表成功或存在表");
    }else{
}];

开启事务后,显得方便很多,不用手动打开数据库,它会自动管理,把任务放在队列中执行,谁也碰不到前面的脚,每个人都很幸福

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(@"创表成功或存在表");
        }else{
    }];
});

像这样做,数据不会同步返回了,界面可以先放个菊花,待数据回调后,再主线程刷新UI,更多开启多线程的方法,可以参考我的另一篇博文 ios 使用多线程

你可能感兴趣的:(iOS FMDB 大数据处理)