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的,只是写的时候就写成了这个样子。