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

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

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

时间: 2024-10-26 09:06:32

runtime 任意类型 model 数据库方便存储的相关文章

boost.any实现任意类型存储

当你需要一个可变的类型时,有三种可能的解决方案: 无限制的类型,如 void*. 这种方法不可能是类型安全的,应该象逃避灾难一样避免它. 可变的类型,即支持多种类型的存储和获取的类型. 支持转换的类型,如字符串类型与整数类型之间的转换. Any实现了第二种方案,一个基于值的可变化的类型,无限可能的类型.这个库通常用于把不同类型的东西存储到标准库的容器中. Any 库如何改进你的程序 任意类型的类型安全存储以及安全的取回 在标准库容器中存放不同类型的方法 可以在无须知道类型的情况下传送类型 Any

数据库中存储日期的字段类型到底应该用varchar还是datetime

将数据库中存储时间的数据类型改为varchar(),这时最好让这些时间是数据库中自动生成的(一个没有格式的输入也可能会导致输出错误),因为存储类型为varchar(),所以获取到的值也就被认为是一个字符串,直接将数据库中的时间字符串进行转化(这时那些转化函数是能识别数据库中的时间函数的),客户端的时间格式不再影响转换过程. 不过数据库中存储时间的类型如果为字符型也会带来一些麻烦: 数据库中的时间仅仅是用来显示.查找的,那么影响还不算大,但如果对时间字段进行一些算法如计算星期.DateDiff.D

Java使用JDBC连接任意类型数据库(mysql oracle。。)

package cn.liz.test; import java.io.InputStream; import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; import java.util.Properties; import org.junit.Test; public class JBDCtest { /** * 编写一个通用的方法, 在不修改源程序的情况下, 可以获取任何数据库的连接

通过数据库评估存储设备IO性能-Oracle 11g IO校准功能介绍

通过数据库评估存储设备IO性能 ---------Oracle11g IO校准功能介绍 前言 I/O子系统是ORACLE数据库的一个重要组成部分,因为I/O操作是贯穿数据库管理全过程,它操作的对象包括日志.表.索引.数据字典.以及一些排序.undo操作等等,每个数据库读取或者写入磁盘上的数据,都会产生磁盘IO,可以这么说一个正常业务的数据库系统,80%的性能消耗都与IO有关,相对于网络.CPU.内存等其他硬件的迅猛发展,磁盘的读写速度的发展却相对滞后,这也导致许多业务性能瓶颈集中在有限的磁盘IO

mysql数据库各存储引擎比较

mysql数据库区别于其他数据库的最重要的一个特点是其插件式的表存储引擎,存储引擎是基于表的,而不是数据库 InnoDB存储引擎: 支持事务,其设计目标主要面向在线事务处理(OLTP)的应用,其特点是行锁设计.支持外键.并支持类似于oracle的非锁定读,即默认读取操作不会产生锁,其将数据放在一个逻辑的表空间中,此外,InnoDB存储引擎支持用裸设备用来建立其表空间,所谓裸设备即是是一种没有经过格式化,不被Unix通过文件系统来读取的特殊块设备文件,是不被操作系统直接管理的设备.这种设备少了操作

MySQL数据库InnoDB存储引擎中的锁机制

MySQL数据库InnoDB存储引擎中的锁机制    http://www.uml.org.cn/sjjm/201205302.asp   00 – 基本概念 当并发事务同时访问一个资源的时候,有可能导致数据不一致.因此需要一种致机制来将访问顺序化. 锁就是其中的一种机制.我们用商场的试衣间来做一个比喻.试衣间供许多消费者使用.因此可能有多个消费者同时要试衣服.为了避免冲突,试衣间的门上装了锁.试衣服的人在里边锁住,其他人就不能从外边打开了.只有里边的人开门出来,外边的人才能进去. - 锁的基本

MySQL更改数据库数据存储目录

MySQL数据库默认的数据库文件位于/var/lib/mysql下,有时候由于存储规划等原因,需要更改MySQL数据库的数据存储目录.下文总结整理了实践过程的操作步骤. 1:确认MySQL数据库存储目录 [[email protected] tmp]# mysqladmin -u root -p variables | grep datadir   Enter password:   | datadir | /var/lib/mysql/   2:关闭MySQL服务 在更改MySQL的数据目录前

数据库的存储引擎和SQL语言

数据库的存储引擎就是管理数据存储的东西,它完成下面的工作: 1)存储机制 2)索引方式 3)锁 4)等等 SQL语言:-----关系型数据库所使用的数据管理语言 1)数据定义语言(DDL):DROP.CREATE.ALTER等对数据对象发生操作的语言. 2)数据操作语言(DML):INSERT .UPDATE. DELETE,对数据本身发生更.删.改. 3)数据查询语言(DQL):SELECT,专门用于查找数据. 4)数据控制语言(DCL):GRANT/授权.REVOKE/收回授权.COMMIT

MySQL 数据库常用存储引擎的特点

数据库的存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据.不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能,使用不同的存储引擎,还可以 获得特定的功能.现在许多不同的数据库管理系统都支持多种不同的数据引擎.MySql的核心就是插件式存储引擎,而其中最知名的就是 MyISAM 及 InnoDB. 存储引擎的查看 查看数据库可配置的存储引擎 SHOW ENGINES; 查看数据库正在使用的存储引擎 show table status fro