如何写一个FMDB帮助类?看看runtime吧

Posted 丶Pz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何写一个FMDB帮助类?看看runtime吧相关的知识,希望对你有一定的参考价值。

  FMDB是一个封装很好的sqllite类库。项目中调用的时候只需要写SQL语句,就能实现数据的CURD。我试过即使手写SQL语句也很麻烦,需要一个字段一个字段的拼上去,而且容易出错。有没有动态获取字段的一种做法呢。当然是有的。在.NET中就有获取一个类的每个字段名称和类型之类的方法。同理,我想OC中肯定也会存在,于是乎,强大的runtime机制就可以拿来用用了。

  为什么用动态的呢,因为动态的拼接表面上就和ORM差不多了,开发者基本不用接触SQL语句,就能实现与数据库的数据交互。下面看具体介绍:

    Class c = [SomeModel Class];

    unsigned int outCount,i;
//class_copyPropertyList方法获取 SomeModel中的字段集合 objc_property_t
*properties = class_copyPropertyList(c, &outCount);

  然后遍历properties,获取到每个字段的字段名称和字段类型

        objc_property_t property = properties[i];
        propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];

propertyType = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];

  这样,类中的每个字段都有了,类型也有了,那么拼接update语句或者insert语句再或者查询都可以。例如: UPDATE TABLE SET A=‘a‘,B=‘b‘,C=1 WHERE 1=1

  字段A,B,C已经能动态取出,a,b,1可以根据新的Model 用 [model objectForKey:]方法获取值。先简单说这么多,下面我通过一个小Demo来演示一下。

  首先实现方法,分析类的字段属性和类型,并存放到一个NSdictionary中。

- (NSDictionary *)pz_getClassPropertyWithClass:(Class)c
{
    //存储列名和列类型的可变数组
    NSMutableArray *propertyNames = [NSMutableArray array];
    NSMutableArray *propertyTypes = [NSMutableArray array];
    
    unsigned int outCount,i;
    
    objc_property_t *properties = class_copyPropertyList(c, &outCount);
    
    //属性名称
    NSString *propertyName;
    NSString *propertyType;
    for (i = 0; i < outCount; i ++) {
        objc_property_t property = properties[i];
        propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        //将不需要的排除
        if ([_cloumnsNotInDB containsObject:propertyName]) {
            continue;
        }
        [propertyNames addObject:propertyName];
        //获取属性类型
        propertyType = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
        
        if ([propertyType hasPrefix:@"[email protected]"]) {
            [propertyTypes addObject:SQLTEXT];
        }else if ([propertyType hasPrefix:@"Ti"]||[propertyType hasPrefix:@"TI"]||[propertyType hasPrefix:@"Ts"]||[propertyType hasPrefix:@"TS"]||[propertyType hasPrefix:@"TB"]) {
            [propertyTypes addObject:SQLINTEGER];
        } else {
            [propertyTypes addObject:SQLREAL];
        }
    }
    free(properties);
    
    return  [NSDictionary dictionaryWithObjectsAndKeys:propertyNames,propertyNameKey,propertyTypes,propertyTypeKey, nil];
}

 然后随便写个Model,调用方法如下:

 NSDictionary *dict = [[PZFMDBUtil sharedUtil] pz_getClassPropertyWithClass:[PZDBModel class]];
    
    NSLog(@"%@",dict);

打印结果为:技术分享

字段名称和类型都有啦,那么拼接  insert  into table (name,age,number,address) values (?,?,?,?) 是不是很easy了呢。然后在调用一下FMDB的方法,就轻松实现Model直接保存或者更新到SQLLITE中了。

例如以下代码:

    PZDBModel *model = [[PZDBModel alloc] init];
    model.name = @"panzi";
    model.number = 12;
    [[PZFMDBUtil sharedUtil] pz_addDataWithModel:model];

我们在看一下数据库:

技术分享

我想,更新查询神马的就不用介绍了吧。当然呢,想在封装一层也是很麻烦的,要考虑好多东西。有时候想想还不如直接写SQL来的爽快~~

 

GitHub:https://github.com/fanpan26/PZFMDBHelper

以上是关于如何写一个FMDB帮助类?看看runtime吧的主要内容,如果未能解决你的问题,请参考以下文章

runtime之玩转成员变量

如何在 FMDB iOS 中启用预写日志记录?

如何在 Swift 中使用“FMDB/SQLCipher”进行加密和解密?

FMDB的线程安全

FMDB 的多线程问题

Runtime objc4-779.1 为什么不能向一个已存在的类添加成员变量?有什么办法达到相同的效果?