码迷,mamicode.com
首页 > 数据库 > 详细

runtime 任意类型 model 数据库方便存储

时间:2015-10-10 23:02:22      阅读:321      评论:0      收藏:0      [点我收藏+]

标签:

//这里边直接上代码 之后我在慢慢地讲解  之后我的QQ:378254160 我有DEMO 方便你们的使用联系我备注 runtime+数据库+任意model类型  当然有时候也是有局限的

//DataBasehandle.m

#import "DataBasehandle.h"

#import <objc/runtime.h>

#import <sqlite3.h>

//http://www.sjsjw.com/kf_mobile/article/4_17043_17742.asp

@interface DataBasehandle ()

@property (nonatomic, copy)NSString *tabelename;

@property (nonatomic, copy)NSDictionary *dic;

@end

 

@implementation DataBasehandle

/* 获取对象的所有属性和属性内容 */

//这个方法 返回的是一个大字典 里边放着所有不为空 的属性和他们的值 属性是Key 值 是 Value

- (NSDictionary *)getAllPropertiesAndVaulesModel:(id)model

{

    NSMutableDictionary *props = [NSMutableDictionary dictionary];

    unsigned int outCount, i;

    objc_property_t *properties = class_copyPropertyList([model class], &outCount);

    for (i = 0; i<outCount; i++)

    {

        objc_property_t property = properties[i];

        const char* char_f =property_getName(property);

        NSString *propertyName = [NSString stringWithUTF8String:char_f];

        id propertyValue = [model valueForKey:(NSString *)propertyName];

        

        /*下面注释的这条语句是这个函数 最开始的语句 目的获取值不为空的属性 我修改之后就可以获取model全部属

         性当然model 属性必须全部写成NSString 类型的 不管实际的类型是什么!*/

         //if (propertyValue) [props setObject:propertyValue forKey:propertyName];

        

        //这样做 就可以获取model对象的全部属性!!!! 下面的代码是我修改的!

        if (propertyValue == nil) {

            [props setObject:@"nil" forKey:propertyName];

        }else

        {

          [props setObject:propertyValue forKey:propertyName];

        }

    }

    free(properties);

    return props;

}

static DataBasehandle * shareDataManager = nil;

//这样可以防止多进程的访问 GCD 写法!!!!!

+(DataBasehandle *) sharedDataBasehandle

{

    static dispatch_once_t once;

    dispatch_once(&once

                  , ^{

                       if (shareDataManager == nil)

                      {

                          shareDataManager = [ [ DataBasehandle alloc ] init ];

                      }

                      

                  });

    return shareDataManager;

}

 

static sqlite3 *db = nil;

 

-(void)openDB

{

    //已经打开完了之后 就不需要再打开了

    if(db != nil)return;

    //获取沙河路径 拼接一个文件的名字

    NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];

    NSString *path = [document stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@",@"adress.sqlite"]];

    NSLog(@"%@",path);

    //打开数据库 初始化数据库了 已经 静态区不为nil了

    int result = sqlite3_open(path.UTF8String, &db);

    if(result == SQLITE_OK)

    {

        //打开成功!

        NSLog(@"打开成功");

    }else

    {

        NSLog(@"打开失败");

    }

}

 

-(void)closeDB

{

    int result = sqlite3_close(db);

    if (result == SQLITE_OK) {

        NSLog(@"关闭成功");

    }else

    {

        NSLog(@"关闭失败");

    }

}

//根据表的名字 和 运行时的model对象 创建一个表!

-(void)createtableName:(NSString *)name Model:(id)model

{

    //根据模型拼接字符串

    NSDictionary *dicstart = [self getAllPropertiesAndVaulesModel:model];

    //这里 必须这样操作一下 变成不可变的字典要不然 遍历的时候 表属性的顺序对应不上!

    NSDictionary *dic = [NSDictionary dictionaryWithDictionary:dicstart];

    self.dic = dic;

    self.tabelename = name;

    NSMutableString *str = [NSMutableString string];

    

    for (id obj in [dic allKeys] )

    {

      [str appendFormat:@" %@ text,",obj];

    }

    NSString *str1 = [str substringToIndex:str.length-1];

    //创建表的SQL语句 CREATE TABLE + 表名(字段 类型 ,...,字段 类型)

    NSString *createStr = [NSString stringWithFormat:@"CREATE TABLE  IF NOT EXISTS  %@(%@)",name,str1];

    NSLog(@"createStr === %@",createStr );

    //第一个参数:在那个数据库里边操作

    //第二个参数:代表要去执行那一条SQL 语句

    //第三个参数:代表那个回调函数

    //第四个参数:回调的一些参数

    //第五个参数:错误信息

    char *error = NULL;

    int result = sqlite3_exec(db, createStr.UTF8String, NULL, NULL, &error);

     printf("massage = %s",error);

    if(result == SQLITE_OK)

    {

        NSLog(@"创表成功");

    }else

    {

        NSLog(@"创表失败");

    }

}

//根据当前创建的表的名字 和运行时model对象 把model对象写入数据库

-(void)insertIntoTableModel:(id)model

{

    NSDictionary *dicstart = [self getAllPropertiesAndVaulesModel:model];

    NSDictionary *dic = [NSDictionary dictionaryWithDictionary:dicstart];

    NSString *name = self.tabelename;

    NSMutableString *strkey = [NSMutableString string];

    NSMutableString *strvalue = [NSMutableString string];

    for (id obj in [dic allKeys] )

    {

        [strkey appendFormat:@" %@,",obj];

        [strvalue appendFormat:@" ‘%@‘,",[dic objectForKey:obj]];

    }

    NSString *strkey1 = [strkey substringToIndex:strkey.length-1];

    NSString *strvalue1 = [strvalue substringToIndex:strvalue.length-1];

    

    //插入语句

    NSString *insertStr = [NSString stringWithFormat:@"INSERT INTO %@(%@) VALUES(%@)",name,strkey1,strvalue1];

    //第一个参数:在那个数据库里边操作

    //第二个参数:代表要去执行那一条SQL 语句

    //第三个参数:代表那个回调函数

    //第四个参数:回调的一些参数

    //第五个参数:错误信息

    NSLog(@"%@",strkey1);

    char *message = NULL;

    int result = sqlite3_exec(db, insertStr.UTF8String, NULL, NULL, &message);

    printf("massage ======= %s",message);

    if(result == SQLITE_OK)

    {

        NSLog(@"插入成功");

    }else

    {

        NSLog(@"插入失败");

    }

}

 

//根据当前的表的名字和运行时model对象  删除 model对象所对应的 一条数据!

-(void)deleteFromTableModel:(id )model

{

    NSDictionary *dicstart = [self getAllPropertiesAndVaulesModel:model];

    NSDictionary *dic = [NSDictionary dictionaryWithDictionary:dicstart];

    NSString *name = self.tabelename;

    NSMutableString *strkey = [NSMutableString string];

    for (id obj in [dic allKeys] )

    {

        if ([ [dic objectForKey:obj ] isKindOfClass:[NSNumber class]] || [ [dic objectForKey:obj ] isKindOfClass:[NSString class]]   )

        {

            [strkey appendFormat:@" %@ = ‘%@‘ and",obj,[dic objectForKey:obj]];

        }

    }

        //去掉最后 四个字符

    NSString *strNew = [strkey substringToIndex:strkey.length-4];

    NSString *deleteStr = [NSString stringWithFormat:@"DELETE FROM %@ WHERE %@",name,strNew];

    char *message = NULL;

    int result = sqlite3_exec(db, deleteStr.UTF8String, NULL, NULL, &message);

    printf("%s",message);

    if(result == SQLITE_OK)

    {

        NSLog(@"删除成功");

    }else

    {

        NSLog(@"删除失败");

    }

}

 

//根据 运行时的model对象 和表的名字 获取所有的 model对象数组

-(NSArray *)selectAllTableModel:(id)model

{

     NSMutableArray  *dataArray = nil;

    //根据模型拼接字符串

    NSDictionary *adddic = self.dic;

    NSString *name = self.tabelename;

    // 查询SQL 语句

    // SELECT * FROM + 表名

    NSString *selectStr = [NSString stringWithFormat:@"SELECT * FROM %@",name];

    sqlite3_stmt *stmt = nil;

    int result = sqlite3_prepare(db, selectStr.UTF8String, -1, &stmt, NULL);

    if (result == SQLITE_OK)

    {

        //定义一个泛型 的指针 在下面会初始化这个泛型具体是什么类型的!不用担心!!!!

        id Model;

        //初始化数组

        dataArray = [NSMutableArray array ];

        

        while (sqlite3_step(stmt) == SQLITE_ROW)

        {

            //这里做的 工作最重要 要不然保存的模型 你是没办法拿到值的!!!!

            //这里根据runtime运行时 创建运行时的对象 这样就可以面对所有的对象!!!! 哈哈哈!

            model = [[ [model class] alloc] init];

            Model = model;

            //记录 表一条数据的位置每次循环的时候 增加!!!!!

            int i = 0;

            for (NSString *key in [adddic allKeys])

            {

                if ([[adddic objectForKey:key] isKindOfClass:[NSString class]] || [[adddic objectForKey:key] isKindOfClass:[NSNumber class]]) {

                  

                    if ([[adddic objectForKey:key] isKindOfClass:[NSString class]])

                    {

                        //这里注意一下可能是 NULL 空的 之后处理一下 避免KVC crash

                        if ((const char *)sqlite3_column_text(stmt, i) == NULL) {

                            [Model setValue:@" " forKey:key];

                        }else

                        {

                            NSString *string = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, i)];

                            [Model setValue:string forKey:key];

                        }

                    } else

                    {

                        NSInteger index = sqlite3_column_int(stmt, i);

                        //这里不用担心 一定能

                        NSString *string = [NSString stringWithFormat:@"%ld", (long)index];

                        [Model setValue:string forKey:key];

                    }

                    i++;

                }

            }

            [dataArray addObject:Model];

          }

    }

    //释放伴随指针

    sqlite3_finalize(stmt);

    return dataArray;

}

 @end

//DataBasehandle.h 中的文件 

 

#import <Foundation/Foundation.h>

@interface DataBasehandle : NSObject

+(DataBasehandle *) sharedDataBasehandle;

 

-(void)openDB;

-(void)closeDB;

 

/* 获取对象的所有属性和属性内容 */

- (NSDictionary *)getAllPropertiesAndVaulesModel:(id)model;

 

-(void)createtableName:(NSString *)name Model:(id)model;

 

-(void)insertIntoTableModel:(id )model;

 

-(void)deleteFromTableModel:(id )model;

 

-(NSArray *)selectAllTableModel:(id)model;

 @end

 

//根据我写的这个 工具类 你可以很方便的存储 根据任意类型的 model 存储到数据库里边 而不用担心数据库不用写 当然前提是你非常明白runtime 运行机制才行  你可以直接存储任意类型的model 当然前提model 里边的所有属性都是 NSString *obj; 类型的这是网络下载下来的数据,当然网络下载的数据可能是 NSNumber类型的 但是不用担心 用NSString接收 之后 显示的时候用 格式化字符串 皆可以解决这个问题!

下面说一下 这个工具类的用法! 很简单!如果现在没有 我就以后会加上的 当然也可以联系我!

 

runtime 任意类型 model 数据库方便存储

标签:

原文地址:http://www.cnblogs.com/yuzhouwjl/p/4868499.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!