iOS简单runtime封装fmdb的使用

iOS简单runtime封装fmdb的使用
学习了iOS有一段时间了,使用到fmdb操作数据库的时候感觉有很多重复性的工作要做,查询数据库时面向对象性感觉很差,一个查询只能针对一个Model,经过了解发现了runtime的使用可以解决这一问题。
使用fmdb的时候相信有过这样的经历查询某个model时:
NSString *sql = @"select * from myFmdb";
    FMResultSet *set = [self.database executeQuery:sql];
    while (set.next) {
        int pid = [set intForColumn:@"id"];
        <span style="color:#ff0000;">NSString *name = [set stringForColumnIndex:1];
        NSInteger age = [set intForColumn:@"age"];</span>
        
        NSLog(@"id==%d,name==%@,age==%ld",pid,name,age);
    }
其中红色的代码是查询的某一个字段,我们不仅要知道字段的类型还要知道字段的位置,用起来就很不方便,而如果model类发生了改变那查询语句也随之改变才行。简单使用runtime可解决此类问题。
使用runtime代码如下(写成了一个方法):
- (NSMutableArray *)finAllWithSql:(NSString *)tableName
                             fmdb:(FMDatabase *)db
                            model:(Class)cls{
    //创建要返回的数组
    NSMutableArray *data = [NSMutableArray array];
    //根据表明查询数据库
    NSString *sql = [NSString stringWithFormat:@"select * from %@",tableName];
    //根据第三方的FMdatabase查询结果集
    FMResultSet *set = [db executeQuery:sql];
    
    //获取该model类的所有的属性列表
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList(cls, &count);
    
    //遍历
    while ([set next]) {
        //根据传进来的类cls,创建对应的对象并保存.
        id obj = [[cls alloc] init];
        
        //遍历所有的属性变量
        for (int i=0; i<count; i++) {
            //得到该属性
            Ivar ivar = ivars[i];
            const char *type = ivar_getTypeEncoding(ivar);
            
            //的到属性的类型用于判断
            NSString *valueType = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
            //得到属性的name使用setKey来设置值,要把属性那么前面的"_"去掉.
            NSString *proName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
            NSString *name = [proName componentsSeparatedByString:@"_"][1];
            
            //判断属性类型,这里仅考虑了NSString,int和float类型(这里吧float转化为了double)
            if ([valueType hasPrefix:@"@"]) {
                //这是NSString类型的,设置值
                [obj setValue:[set stringForColumnIndex:i] forKey:name];
                
            }else if([valueType hasPrefix:@"q"]|[valueType hasPrefix:@"i"]){
                //"q"代表的是NSInteger类型,这是NSInteger类型的,设置值
                [obj setValue:@([set intForColumnIndex:i]) forKey:name];
                
            }else if ([valueType hasPrefix:@"f"]){
                //这是float类型的,设置值
                [obj setValue:@([set doubleForColumnIndex:i]) forKey:name];
                
            }
        }
        //将该字典存储到数组中.
        [data addObject:obj];
    }
    return data;
}
现对以上代码进行说明,首先传进来的参数有查询的表名,要查询的数据库以及查询的model类,使用fmdb查询后得到查询结果集,通过
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(cls, &count);
得到model类的属性列表,然后遍历结果集,然后遍历属性列表的属性,
const char *type = ivar_getTypeEncoding(ivar);
得到的是属性的类型,之后的几条语句是将这个类型进行处理以用于判断, if语句是用于判断属性类型的,这里仅仅只是展示了三种类型,把属性值通过setValue forKey的方式复制给通过传进来的参数 cls创建的类,然后保存到数组中。最后返回数组。
可以看出要想查询结果只要传进来几个参数就行了,最后返回的数组保存的是id类型的,用的时候强转一下就好了。
第一次写博客,希望方便大家学习,也方便自己学习进步,望大家指教。runtime的使用还是菜鸟,很多地方也有待改正望大神斧正。其实也可以封装sqlite的,只是写的时候就写成了这个样子。


    



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值