FMDB和model结合使用

187 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

需求

最近音频类项目,有一个模块,收听过的内容,需要存在本地,需要记录收听的时长,下次接着播放。上限50条,按收听时间倒序展示

方案

设计本地数据库,用FMDB 执行sql语句。考虑到数据库不止这个地方用到。后续的收藏,订阅也有可能需要存到本地。所以数据库需要复用

需要解决的问题

SQL的增删改查:

  • 建表:create table if not exists 'tablename' (column1 类型, column2 类型...)
  • 增 insert into 'tablename' (key1,key2...) values (v1,v2...)
  • 删 delete from 'tablename' where key = value
  • 改 update 'tablename' set key1 = v1, key2 = v2 where key = v
  • 查 select * from 'tablename' where key = v

问题一: 需要获取model的属性,和类型,建表 插入 查询都需要 解决

**unsigned** **int** count = 0;

    objc_property_t *properties = class_copyPropertyList(class, &count);

    **for** (**int** i = 0; i<count; i++) {

        objc_property_t propertyx = properties[i];

        NSString *propertyName = [NSString stringWithUTF8String:property_getName(propertyx)];

        **const** **char** *propertyChar = property_getAttributes(propertyx);

        NSString *propertyNamex = [NSString stringWithUTF8String:propertyChar];

        NSString *typeKey = [propertyNamex componentsSeparatedByString:@","][0];

        NSString *typeStr = [typeDict objectForKey:typeKey];

        **if** (!typeStr || typeStr.length<1) {

            typeStr = @"text";

        }

        **if** ([propertyName isEqualToString:primaryKey]) {

            **continue**;

        }

        [sql appendFormat:@",'%@' %@", propertyName,typeStr];

    }

    [sql appendString:@")"];

问题二:数据存储上限50条,这里面会有更新,所以不能按照插入的顺序删除,考虑到取数据的时候也是按照更新的事件排序,所以加个时间的字段,每次插入成功的时候判断当前count 大于50进行删除

//查询数量

-(**int**)searchCountPrimaryKey:(NSString *)primaryKey

{

    NSString *sql = [NSString stringWithFormat:@"SELECT COUNT(%@) FROM %@",primaryKey,**self**.tableName];

    FMResultSet *s = [**self**.db executeQuery:sql];

    **if** ([s next]) {

    **int** totalCount = [s intForColumnIndex:0];

        **return** totalCount;

    }

    **return** 0;

}

//超过50条 删除

-(**void**)deleteMoreThan:(**int**)value

{

    NSString *sql =[NSString stringWithFormat:@"DELETE FROM %@ AS t WHERE t.timestr <= (SELECT t1.timestr FROM %@  AS t1 ORDER BY t1.timestr DESC LIMIT %d,1)", **self**.tableName,**self**.tableName,value];

    **BOOL** result = [**self**.db executeUpdate:sql];

    **if** (result) {

        NSLog(@"删除成功");

    }**else**{

        NSLog(@"删除失败");

    }

}

最终成果:

  • 建表,这里根据实际情况设置了主键,数据来自服务端,所以主键不自增, 和服务端数据保持一致。考虑到其他地方可能需要自增主键,就都加上
-(**BOOL**)creatData:(Class)class primary:(NSString *)primaryKey isAutoincrement:(**BOOL**)isIncrement

{

    NSDictionary *typeDict  = @{@"Ti":@"integer",@"TB":@"integer",@"T@\"NSString\"":@"text"};

    

    NSMutableString * sql = [NSMutableString stringWithFormat:@"create table if not exists '%@' (", **self**.tableName];

//    [sql appendString:@"'%@' test primary key ",uniqueKey];

    **if** (isIncrement) {

        [sql appendFormat:@"'%@' integer primary key autoincrement",primaryKey];

    }**else**{

        [sql appendFormat:@"'%@' test primary key ",primaryKey];

    }

    

    **unsigned** **int** count = 0;

    objc_property_t *properties = class_copyPropertyList(class, &count);

    **for** (**int** i = 0; i<count; i++) {

        objc_property_t propertyx = properties[i];

        NSString *propertyName = [NSString stringWithUTF8String:property_getName(propertyx)];

        **const** **char** *propertyChar = property_getAttributes(propertyx);

        NSString *propertyNamex = [NSString stringWithUTF8String:propertyChar];

        NSString *typeKey = [propertyNamex componentsSeparatedByString:@","][0];

        NSString *typeStr = [typeDict objectForKey:typeKey];

        **if** (!typeStr || typeStr.length<1) {

            typeStr = @"text";

        }

        **if** ([propertyName isEqualToString:primaryKey]) {

            **continue**;

        }

        [sql appendFormat:@",'%@' %@", propertyName,typeStr];

    }

    [sql appendString:@")"];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, **YES**);

    NSString *documentDirectory = [paths objectAtIndex:0];

\


    NSString *infraredDataBasePath = [documentDirectory stringByAppendingPathComponent:@"gjwavee.db"];

    NSLog(@"path==%@",infraredDataBasePath);

    FMDatabase *db = [FMDatabase databaseWithPath:infraredDataBasePath];

    **self**.db = db;

    **if** ([db open]) {

        NSLog(@"打开成功");

        **if** ([db executeUpdate:sql]) {

            NSLog(@"创建表成功!");

            **return** **YES**;

        }**else** {

            **return** **NO**;

        }

    }**else**{

        NSLog(@"open error");

        **return** **NO**;

    }

}
  • 查询所有 这里不想耦合字典转模型的内容,所以就返回字典数组
- (NSMutableArray *)queryAllData:(Class)class {

    NSString * sql = [NSString stringWithFormat:@"select * from '%@'", **self**.tableName];

    FMResultSet * resultSet = [**self**.db executeQuery:sql];

    **id** model = **nil**;

    

    NSMutableArray * mArr = [NSMutableArray arrayWithCapacity:0];

    **while** ([resultSet next]) {

        model = [class new];

        NSMutableDictionary *mutabDict = [NSMutableDictionary dictionary];

        **unsigned** **int** count = 0;

        objc_property_t *properties = class_copyPropertyList(class, &count);

        **for** (**int** i = 0; i<count; i++) {

            objc_property_t propertyx = properties[i];

            NSString *key = [NSString stringWithUTF8String:property_getName(propertyx)];

            [mutabDict setValue:[resultSet stringForColumn:key] forKey:key];

        }

        [mArr addObject:mutabDict];

    }

    **return** mArr;

}

剩下的增删改查就不一一列出来,稍后放到github上去