博客> FMDB 使用心得之一
FMDB 使用心得之一
2017-10-19 07:59 评论:0 阅读:684 tianya2416
runtime 运行时 FMDB 数据库

以往我们在使用数据库的时候往往是把一个对象的每一个字段一一存到数据库的表里面;当然这种情况对于字段比较少的对象是比较好的选择,但是当这个对象有100个字段的时候是不是会出现很麻烦的情况。 今天使用一种比较方便的存储方式,使用runtime 将对象归档,难后用data的形式存到数据库里面。

1.我们现来声明一个对象:

 @interface weishengModel : NSObject
@property(nonatomic, copy)NSString * user_id;
@property(nonatomic, copy)NSString * name;
@property(nonatomic, assign)int      age;
@property(nonatomic, assign)float    height;
@end

2.用runtime的形式对对象归档

- (void)encodeWithCoder:(NSCoder *)coder
{
    //  NSLog(@"%s",__func__);
    Class cls = [self class];
    while (cls != [NSObject class]) {
        /*判断是自身类还是父类*/
        BOOL bIsSelfClass = (cls == [self class]);
        unsigned int iVarCount = 0;
        unsigned int propVarCount = 0;
        unsigned int sharedVarCount = 0;
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*变量列表,含属性以及私有变量*/
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*属性列表*/
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;

        for (int i = 0; i < sharedVarCount; i++) {
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i));
            NSString *key = [NSString stringWithUTF8String:varName];
            /*valueForKey只能获取本类所有变量以及所有层级父类的属性,不包含任何父类的私有变量(会崩溃)*/
            id varValue = [self valueForKey:key];
            if (varValue) {
                [coder encodeObject:varValue forKey:key];
            }
        }
        free(ivarList);
        free(propList);
        cls = class_getSuperclass(cls);
    }
}
- (id)initWithCoder:(NSCoder *)coder
{
    //  NSLog(@"%s",__func__);
    Class cls = [self class];
    while (cls != [NSObject class]) {
        /*判断是自身类还是父类*/
        BOOL bIsSelfClass = (cls == [self class]);
        unsigned int iVarCount = 0;
        unsigned int propVarCount = 0;
        unsigned int sharedVarCount = 0;
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*变量列表,含属性以及私有变量*/
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*属性列表*/
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;

        for (int i = 0; i < sharedVarCount; i++) {
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i));
            NSString *key = [NSString stringWithUTF8String:varName];
            id varValue = [coder decodeObjectForKey:key];
            if (varValue) {
                [self setValue:varValue forKey:key];
            }
        }
        free(ivarList);
        free(propList);
        cls = class_getSuperclass(cls);
    }
    return self;
}

3.接下来就是用FMDB对数据库进行操作

(1)、创建数据库

 -(id)init
{
    if (self = [super init]) {

        NSString * stringPath = [NSHomeDirectory() stringByAppendingString:@"/Documents/House"];
        if (![[NSFileManager defaultManager] fileExistsAtPath:stringPath]) {
            BOOL res = [[NSFileManager defaultManager]createDirectoryAtPath:stringPath withIntermediateDirectories:YES attributes:nil error:nil];
            if (res) {
                NSLog(@"create successful");
            }
        }
        NSString * dbPatch = [stringPath stringByAppendingPathComponent:@"weisheng.sqlite"];
        _dataBase = [FMDatabase databaseWithPath:dbPatch];
        [self createDateBaseTable];
    }
    return self;
}

(2)、创建表

  - (void)createDateBaseTable
{

    if ([_dataBase open]) {
        NSString * v5TableSql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS ContactsGroup (id INTEGER PRIMARY KEY AUTOINCREMENT ,data text,user_id text)"];

        BOOL res = [_dataBase executeUpdate:v5TableSql];
        [_dataBase close];
        if (!res) {
            NSLog(@"error when creating db table");
        } else {
            NSLog(@"success to creating db table");
        }

    }
}

(3)、插入数据

    - (void)insertTheDataToGroupDataBase:(weishengModel *)modelObject
{
    if ([_dataBase open]) {
        [_dataBase beginTransaction];
        NSData * data = [self archivedDataForOfflineResourceData:modelObject];
        NSString * v5TableSql = [NSString stringWithFormat:@"insert or replace into ContactsGroup (data,user_id) values (?,?)"];
        BOOL res = [_dataBase executeUpdate:v5TableSql withArgumentsInArray:@[data,modelObject.user_id]];
        if (!res) {
            NSLog(@"error when insert db table");
        } else {
            NSLog(@"success to insert db table");
            [_dataBase commit];
        }
         [_dataBase close];
    }
}

(4)、更新数据

- (void)updateTheDataToGroupDataBase:(weishengModel *)modelObject
{
    if ([_dataBase open]) {
        [_dataBase beginTransaction];
        NSData * data = [self archivedDataForOfflineResourceData:modelObject];
        NSString * v5TableSql = [NSString stringWithFormat:@"insert or replace into ContactsGroup (data,user_id) values (?,?)"];
        BOOL res = [_dataBase executeUpdate:v5TableSql withArgumentsInArray:@[data,modelObject.user_id]];
        if (!res) {
            NSLog(@"error when update db table");
        } else {
            NSLog(@"success to update db table");
            [_dataBase commit];
        }
        [_dataBase close];
    }
}    

(5)、数据查询

    - (void)readTheDataToGroupDataBase:(void(^)(NSArray * arrayData))readTheDataToDataBaseBlock
{
    if ([_dataBase open]) {
        NSString * sql = [NSString stringWithFormat:
                          @"select * from ContactsGroup order by user_id"];
        FMResultSet * rs = [_dataBase executeQuery:sql];
        NSData * data;
        NSMutableArray * array = [[NSMutableArray alloc]init];
        while ([rs next])
        {
            data = [rs dataForColumn:@"data"];
            weishengModel * model = [self unarchiveForData:data];
            [array addObject:model];
        }
        [_dataBase close];
        readTheDataToDataBaseBlock(array);
    }
}

(6)、删除数据

    - (void)deleteTheDataToGroupDataBase:(weishengModel *)modelObject
{
    if ([_dataBase open]) {
        [_dataBase beginTransaction];
        NSString * v5TableSql = [NSString stringWithFormat:@"delete from ContactsGroup where user_id = %@",modelObject.user_id];
        BOOL res = [_dataBase executeUpdate:v5TableSql];
        if (res) {
            [_dataBase commit];
            NSLog(@"success to delete db table data");
        }else
        {
            NSLog(@"error when delete db table data");
        }
        [_dataBase close];
    }
}

(7)、删除表

    - (void)DropTheTableGroupDataBase
{
    if ([_dataBase open]) {
        NSString * sqlstr = [NSString stringWithFormat:@"drop table ContactsGroup"];
        BOOL res =  [_dataBase executeUpdate:sqlstr];
        if (res) {
            NSLog(@"drop table successful");
        }else
        {
            NSLog(@"drop table fail");
        }
        [_dataBase close];
    }
}

(8)、数据的互转

    - (NSData *)archivedDataForOfflineResourceData:(weishengModel * )data
{
    NSData * resData = nil;

    @try {
        resData = [NSKeyedArchiver archivedDataWithRootObject:data];

    }
    @catch (NSException *exception) {
        NSLog(@"%s,%d,%@", __FUNCTION__, __LINE__, exception.description);
        resData = nil;
    }
    @finally {

    }

    return resData;
}
    - (id)unarchiveForData:(NSData*)data
{

    id resObj = nil;
    @try {
        resObj = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    }
    @catch (NSException *exception) {
        NSLog(@"%s,%d,%@", __FUNCTION__, __LINE__, exception.description);
        resObj = nil;
    }
    @finally {

    }

    return resObj;
}

其实大家应该发现了这种写法有线程安全问题、下一篇就来介绍下使用FMDB如何避免线程问题。

收藏
2
sina weixin mail 回到顶部