文档章节

Runtime机制封装数据库

C
 Coder_Funy
发布于 2016/01/23 21:51
字数 1430
阅读 3
收藏 0

1、导入libsqlite3.dylib,这个没有什么要说的。

2、主要方法和参数:

        +(DataBasehandle *) sharedDataBasehandle; //数据库单例对象,全局引用

        -(void)createtableName:(NSString *)name Modelclass:(Class)modelClass; //创建表

        -(void)insertIntoTableModel:(id )model; //插入Model

        -(void)deleteFromTableModel:(id )model; //删除Model

        -(void)updateFromAttributeName:(NSString *)attributeName Oldstring:(NSString *)oldname NewString:(NSString *)newstring; //实现字段替换

        -(NSMutableArray *)selectFromAttributeName:(NSString *)attributeName ValueStr:(NSString *)valueStr; //数据查询

        -(void)DeleteTbaleName:(NSString *)tableName; // 删除表

3、代码实现

- (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)createtableName:(NSString *)name Modelclass:(Class)modelClass
{
        //省略打开数据库的步骤
        [shareDataManager openDB];
        //这里创建一个新的 以查询的时候下边使用
         _saveClass = modelClass;
         id model = [[modelClass alloc] init];
    
        //根据模型拼接字符串
        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];
        MyLog(@"createStr === %@",createStr );
        
        
        //第一个参数:在那个数据库里边操作
        //第二个参数:代表要去执行那一条SQL 语句
        //第三个参数:代表那个回调函数
        //第四个参数:回调的一些参数
        //第五个参数:错误信息
        
        char *error = NULL;
        int result = sqlite3_exec(db, createStr.UTF8String, NULL, NULL, &error);
        
        printf("message = %s",error);
        
        if(result == SQLITE_OK)
        {
            MyLog(@"创表成功");
        }else
        {
            MyLog(@"创表失败");
        }
}


//基于运行时,将Model数据插入数据库
-(void)insertIntoTableModel:(id)model
{
    if (model != nil)
    {
        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("message ======= %s",message);
        if(result == SQLITE_OK)
        {
            MyLog(@"插入成功");
        }else
        {
            MyLog(@"插入失败");
        }
        
        
    }
    else
    {
        MyLog(@"model为空不能操作!!!!");
    }
    
}


//删除某条数据

-(void)deleteFromTableModel:(id )model
{
    if (model != nil)
    {
        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)
        {
            MyLog(@"删除成功");
        }else
        {
            MyLog(@"删除失败");
        }
    }else
    {
        MyLog(@"model为空不能操作!!!!");
    }
}

//获取数据

-(NSMutableArray *)selectAllModel
{
    //初始化数组
    NSMutableArray *dataArray = [NSMutableArray array ];
    //根据模型拼接字符串
    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;
        
        
        while (sqlite3_step(stmt) == SQLITE_ROW)
        {
            //这里做的 工作最重要 要不然保存的模型 你是没办法拿到值的!!!!
            //这里根据runtime运行时 创建运行时的对象 这样就可以面对所有的对象!!!! 哈哈哈!
            Model = [[_saveClass alloc] init];
            
            //记录 表一条数据的位置每次循环的时候 增加!!!!!
            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;
}


//删除表

-(void)DeleteTbaleName:(NSString *)tableName
{

    
//    坑!这个是删除一个表中的所有数据而已 也就是清空这张表
//    NSString *createStr = [NSString stringWithFormat:@"delete from %@",tableName];
    
    //这才是删除一张表
    NSString *createStr = [NSString stringWithFormat:@"DROP TABLE  %@",tableName];
    //第一个参数:在那个数据库里边操作
    //第二个参数:代表要去执行那一条SQL 语句
    //第三个参数:代表那个回调函数
    //第四个参数:回调的一些参数
    //第五个参数:错误信息
    
    char *error = NULL;
    int result = sqlite3_exec(db, createStr.UTF8String, NULL, NULL, &error);
    
    printf("message = %s",error);
    if(result == SQLITE_OK)
    {
        MyLog(@"删除表成功");
    }else
    {
        MyLog(@"删除表失败");
    }
}




© 著作权归作者所有

共有 人打赏支持
C
粉丝 0
博文 2
码字总数 2453
作品 0
高级程序员
私信 提问
Go语言中实现基于 event-loop 网络处理

Go语言中实现基于 event-loop 网络处理 鸟窝2017-11-291 阅读 Go 我们知道, Go语言为并发编程提供了简洁的编程方式, 你可以以"同步"的编程风格来并发执行代码, 比如使用 关键字新开一个g...

鸟窝
2017/11/29
0
0
iOS 平台前所未有的 Sqlite 封装 (增、删、改、查、一行代码完成)

1. 支持多线程调用 2. 多线程安全处理机制 3. 一行代码操作数据库 (增、删、改、查) 4. 基于 runtime 技术和 sqlite api 完美打造 5. 支持多表联查

netyouli
2016/11/15
1
0
基于FMDB数据库操作类--LKFMDB

LKFMDB是一种数据库操作类。可对FMDB面向对象封装,支持任意类型主键,可对每个字段修饰,傻瓜式操作,一键即可保存更新。 支持SQLCipher加密(见 demo): 默认为加密模式 如需要取消在fmdb文件...

匿名
2016/03/22
918
0
Angelo/FMDB_runtime

#FMDB_runtime /** * 对 sqlite 的使用进行简单封装,仅涉及简单的单表 增删改查 * * 基于 FMDB * * 操作基于 model ,数据库表字段与 model 属性一一对应,对 model 整体进行操作 * * 根据 mo...

Angelo
2015/12/16
0
0
runtime 运行时机制 完全解读

我们前面已经讲过一篇runtime 原理,现在这篇文章主要介绍的是runtime是什么以及怎么用!希望对读者有所帮助! 首先,第一个问题,1》runtime实现的机制是什么,怎么用,一般用于干嘛?这个问...

哥特复心
2014/08/06
0
10

没有更多内容

加载失败,请刷新页面

加载更多

MYSQL事务处理

INNODB 事务里,所有表引擎必须为INNODB,在非实务表上操作,不会警告,不会报错,但没有效果

关元
25分钟前
1
0
cmake 编译脚本

#!/bin/sh test -d build || mkdir -p build cd build cmake .. make

shzwork
43分钟前
2
0
从零开始实现Vue简单的Toast插件

概述: 在前端项目中,有时会需要通知、提示一些信息给用户,尤其是在后台系统中,操作的正确与否,都需要给与用户一些信息。 1. 实例 在Vue组件的methods内,调用如下代码 `this``.$toast({...

前端小攻略
48分钟前
1
0
yaf和yaconf

pecl install yafpecl install yaconf [yaf] yaf.environ = dev yaf.use_spl_autoload = On yaf.use_namespace = 1 [yaconf] yaconf.directory = /data/wwwroot/yaconf......

果树啊
48分钟前
0
0
day01:shell基础(shell基础、alias及重定向)

1、shell基础介绍: shell是一个命令解释器,用于用户与机器的交互: 也支持特定的语法(逻辑判断,循环): 每个用户都有自己特定的shell:Centos7的shell是bash(bourne agin shell): shel...

芬野de博客
51分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部