[iOS]JKDBModel源码解读
2017-08-14 本文已影响157人
阿不不不不
JKDBModel是一个对FMDB进行二次封装的一个轻量级框架,进一步简化了sql语句,也便于对数据库进行管理。使用runtime机制,使得设计更为巧妙,我在原有代码基础上添加了更多的注释。以下通过保存一组数据的例子来走走通整个工作流程。
调用save对数据进行保存操作时
1.png会最先调用+ (void)initialize方法,在此方法内调用creaTable方法
2.png 3.png+(BOOL)creatTable方法中,创建了单例,通过jkdb.dbQueue实现了图4中dbQueue的get方法,通过这几个方法创建了数据库
4.png
在这几个方法中创建了与框架名相同的数据库接下来就需要创建表,回看图3中的
//该类的类名作为表名(通过用runtime的中的方法获得)
NSString *tableName = NSStringFromClass(self.class);
//获取数据库表每一列的类型的并转成字符串来进行sql操作
NSString *columeAndType = [self.class getColumeAndTypeString];
关键看第二个方法,如何获得该类的属性使之作为数据表每一列的列名和列的类型
5.png先是从NSDictionary *dict = [self.class getAllProperties];返回的字典拼接从创建表所需的字符串
6.png
而这个方法是将getAllProperties返回的字典数据中的列名与属性拼接成字符串,以便作为操作数据库的字符串
7.png
其实这个方法也是通过runtime中的方法获得该类的属性。
这样数据库和表就建好了,接下来就是保存数据
因为在调用save方法之前已经调用了一次-init()方法,在图2中可以看出,在此方法中执行了NSDictionary *dic = [self.class getAllProperties];来获得表中的列名及列类型分别保存在两个数组中,在save方法进行引用:注释中有注释主要的语句的用法
8.png
一点小小的补充
其实在我对表进行更新操作时发现,我针对特定行进行数据更新时需要先获得主键作为索引找到我要更新的那个行的数据,但我是没办法知道我要更新数据的那个行的主键值的,要更新成功的话必须从第一行开始更新,每更新一个必须对变量+1作为主键的索引条件
框架的demo.png
最后我添加了一个方法,可用能拿得到的数据中可以作为唯一能识别的列的数据作为索引条件
/** 更新单个对象 */
//updataStr:作用索引条件的数据
//updataName:作为索引条件的列名
- (BOOL)update:(NSString*)updataStr updataName:(NSString *)updataName
{
JKDBHelper *jkDB = [JKDBHelper shareInstance];
__block BOOL res = NO;
[jkDB.dbQueue inDatabase:^(FMDatabase *db) {
NSString *tableName = NSStringFromClass(self.class);
NSMutableString *keyString = [NSMutableString string];
NSMutableArray *updateValues = [NSMutableArray array];
//第一列为主键不添加进来
for (int i = 1; i < self.columeNames.count; i++) {
NSString *proname = [self.columeNames objectAtIndex:i];
[keyString appendFormat:@" %@=?,", proname];
id value = [self valueForKey:proname];
if (!value) {
value = @"";
}
[updateValues addObject:value];
}
//删除最后那个逗号
[keyString deleteCharactersInRange:NSMakeRange(keyString.length - 1, 1)];
NSString *sql = [NSString stringWithFormat:@"UPDATE %@ SET %@ WHERE %@ = '%@';", tableName, keyString,updataName,updataStr];
res = [db executeUpdate:sql withArgumentsInArray:updateValues];
NSLog(res?@"更新成功":@"更新失败");
}];
return res;
}