//这里边直接上代码 之后我在慢慢地讲解  之后我的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接收 之后 显示的时候用 格式化字符串 皆可以解决这个问题!

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

//首先创建 一个工具类

db = [[DataBasehandle alloc] init];

[db openDB];

//为了获取这个类 运行时的属性与对象值 创建model而已

model = [[ActivityModelevent1 alloc] init];

//创建 固定格式的表 这里注意一个类型的model 对应一个表格的名字

[db createtableName:@"activitymodel" Model:model];

//读取数据库里边的所有 model 组成的数组 变成可变数组 付给self.dataArray

self.dataArray =  [NSMutableArray arrayWithArray:[db selectAllTableModel:model]];

当然你也可以 增加和修改 如下

//创建一个新的model1 任意类型都可以 你的model 但是必须和你的 表名 是一直的 这也就是 runtime 的优点 也是缺点

model1 = [[ActivityModelevent1 alloc] init];

//增加 一个model1 在当前表名

[db insertIntoTableModel:model1];

//删除 一个model1 在当前表名

[db deleteFromTableModel:model1];

通过上面的简单的操作 根据runtime 运行时的好处 大家就可以 通过我的工具类 不必操作 数据库 就能把 model 数据存储和 删除了 非常简单! 当然这样虽然方便 也有他的弊端 大家了解了我的 思想就会 非常明白这个 弊端了 ,劝大家还是好好学习一下Sqlite 这才是王道,我现在懒得学习哈哈,就这样,大家下次见。

转载于:https://www.cnblogs.com/yuzhouwjl/p/4868499.html

runtime 任意类型 model 数据库方便存储相关推荐

  1. 1009MySQL数据库InnoDB存储引擎Log漫游

    00 – Undo Log Undo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atom ...

  2. 数据库中存储日期的字段类型究竟应该用varchar还是datetime ?

    背景: 前段时间在百度经验看到一篇文章<如何在电脑右下角显示你(爱人)的名字>,之前也听过这个小技巧,但没真正动手设置过.所以出于好奇就实践了一下. 设置完成后的效果例如以下.右下角的时间 ...

  3. mysql gettimestamp_使用mysql数据库,存储日期字段使用timestamp类型的时候,取出来的数据最后面会多一个.0 【解决方案】...

    mysql数据库,存储日期字段使用timestamp类型的时候,取出来的数据最后面会多一个.0 . 看似是YYYY-MM-DD HH:MM:SS,但其实应该是yyyy-MM-dd hh:mm:ss.f ...

  4. 数据库可以存储哪些类型的数据

    baidu了很久,也不知道是不是因为baidu垃圾,才入门数据库,不知道数据库能存储哪些类型的数据,网上搜了半天没有搜到答案,因此,自己理解就是电脑上的一切数据都是按着二进制来存储,因此数据库是可以存 ...

  5. 使用Mono.Cecil辅助ASP.NET MVC使用dynamic类型Model

    使用Mono.Cecil辅助ASP.NET MVC使用dynamic类型Model 2011-09-06 00:21 by 老赵, 8645 visits 这也是之前在珠三角技术沙龙上的示例之一,解决 ...

  6. 数据库之存储引擎,数据类型-30

    数据库之存储引擎,数据类型-30 数据存储引擎 什么是引擎 ? 一个功能的核心部分        引擎可以被分类 为什么要分类? 自然 增压的 汽油 柴油 电动 混合动力 天然气 核动力 烧水 汽油 ...

  7. 【数据库考试】数据库是存储在计算机内结构化的数据的集合

    (1)(数据库)是存储在计算机内结构化的数据的集合 (2)下述关于数据系统正确的描述是(数据库系统减少了数据冗余). (3)数据库(DB).与数据库系统(DBS)和数据库管理系统(DBMS)之间的关系 ...

  8. SQL--数据库的操作(DDL,DML,DQL)+使用命令查看当前数据库的存储位置(数据库版本查询)

    文章目录 SQL--数据库的操作 DDL---操作数据库 DDL---操作表 DML-增删改查 DQL-对表数据基础查询 Navicat的安装使用(MySQL图形化界面) 数据类型 使用命令查看当前数 ...

  9. 在SQL Server中保存和输出任意类型的文件

    我们可以把任意类型的文件保存到SQL Server中,在进行例子之前,先建立测试用表格,TestFile.sql: if exists (select * from dbo.sysobjects wh ...

最新文章

  1. jQuery元素内容操作的方法有多少种?
  2. python多线程扫描_python实现多线程扫描网站目录
  3. VirtualBox 使用 NAT 方式网络的 SSH 连接
  4. java 多线程 8 : 线程通信
  5. 【深入理解编译】深入理解编译
  6. linux 脚本做成服务,Shell脚本注册到Linux系统服务实例
  7. java sdk怎么配置_Java SDK环境配置教程
  8. Hadoop学习笔记(基于《10小时入门大数据》)
  9. vue 富文本编辑器上传图片到服务器并显示到富文本中
  10. 九章云极DataCanvas公司荣获机器之心三大奖项,助力产业数智化升级
  11. 使用插件导入Excel表到数据库
  12. CWE ID 259:Use of Hard-coded Password
  13. ECMALL买家取消退款
  14. 微信或QQ屏蔽域名,爆红域名如何在微信打开,如何进行微信域名防封?
  15. 聊聊ThoughtWorks面试(郑大版 社招)+ PS:应届生简单流程介绍
  16. 数据库原理--概念模型
  17. JNPF移动办公解决方案
  18. ​未名企鹅极客 | 流向处理新技术
  19. Justice, grandson of interest!
  20. 对计算机系学生的七个建议

热门文章

  1. 深入理解 Mybatis 插件开发
  2. 优雅的使用 ThreadLocal
  3. 山东省第三届数据应用赛事来了!
  4. 深入浅出统计学(十)抽取样本
  5. 用Transformer完全替代CNN?
  6. 建议给予导师决定硕博士能否毕业的自主权?教育部:将充分采纳!
  7. 可高效训练超大规模图模型,PyTorch BigGraph是如何做到的?
  8. 600页!分享珍藏很久的《推荐系统学习手册》(附下载链接及入门经验)
  9. 神操作!美国程序员把工作外包给中国程序员,上班摸鱼吸猫年入 20 万美元
  10. 一张图看懂中科大、国科大、中科院、社科院、上科大之间的关系