IOS与sqlite及归档(更新)
IOS与sqlite及归档
起因
业务需求!以前项目都是用到归档!很小用数据库!所有特意研究sqlite数据库及其封装~~~
归档优缺点
- 1 简单
- 2 数据量大时效率低下,且不能增量改变,必须一次写入
数据库优缺
- 1 可以增量改变
- 2 相对于归档比较复杂
sqlite
使用
已封装为已类名为表头,一张表占一个库文件,直接引入*.h *.m 就可以用了
封装涉及知识点
- 1 objc_property_t 动态获取实例属性(反射机制)
//实例类
Class model_class = [model class];
NSMutableDictionary * sub_model_info = [NSMutableDictionary dictionary];
unsigned int property_count = 0;
//类包含对象数量
objc_property_t * propertys = class_copyPropertyList(model_class, &property_count);
for (int i = 0; i < property_count; i++) {
//每个对象的属性
objc_property_t property = propertys[i];
//对象名
const char * property_name = property_getName(property);
//对象属性
const char * property_attributes = property_getAttributes(property);
NSString * property_name_string = [NSString stringWithUTF8String:property_name];
NSString * property_attributes_string = [NSString stringWithUTF8String:property_attributes];
//基础类 备注:如 int,bool property_attributes_list.count = 1
NSArray * property_attributes_list = [property_attributes_string componentsSeparatedByString:@"\""];
}
- 2 sqlite 建表 字段
//将类对象利用 动态获取实例属性 ,根据类型判断转为sql语句,并且在语句创建时 必须加上_id(属性 主键且唯一),如遇到子类则递归创建方法 (建议 基本对象不要超过2层)
CREATE TABLE IF NOT EXISTS SqlTestModel (_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,dataVal BLOB DEFAULT NULL,boolVal INTERGER DEFAULT 0,numberVal INTERGER DEFAULT 0,subModel INTERGER DEFAULT 0,boolVal2 INTERGER DEFAULT 0)
- 3 sqlite 改表 字段
// sqlite 没有删表的字段功能,所以曲线处理.
1.旧表改名
NSString* rename_table_sql = [NSString stringWithFormat:@"alter table %@ rename to temp_tab",table_name];
2.以新对象建表
3.判读新表含有哪些旧表字段
NSArray * new_model_field_name_array = [self getModelFieldNameWithClass:model_class];
NSMutableString * newField = [[NSMutableString alloc]init];
for (NSString* field in new_model_field_name_array) {
NSInteger idx = [old_model_field_name_array indexOfObject:field];
if (idx != NSNotFound) {
[newField appendString:[NSString stringWithFormat:@"%@ ,",field]];
}
}
4.导入旧表数据到新表
NSString* insert_table_sql = [NSString stringWithFormat:@"insert into %@(%@) select %@ from %@ where 1=1 ",table_name,newField,newField,@"temp_tab"];
5.删除旧表
NSString* drop_table_sql = [NSString stringWithFormat:@"drop table %@",@"temp_tab"];
- 4 增删改查
注意事项
1. 要加锁
@property (nonatomic, strong) dispatch_semaphore_t dsema;
self.dsema = dispatch_semaphore_create(1);
+ (void)insert:(id)model_object {
dispatch_semaphore_wait([self shareInstance].dsema, DISPATCH_TIME_FOREVER);
@autoreleasepool {
// [[self shareInstance].sub_model_info removeAllObjects];
// [self insertModelObject:model_object];
}
dispatch_semaphore_signal([self shareInstance].dsema);
}
2. 要先处理自定义类里面,包含其自定义类,并优先存入
3. 多条命令写入,要加事务处理
[self execSql:@"BEIGIN"];
//要处理内容
[self execSql:@"COMMIT"];
- 5 runtime技巧 setter getter
@interface PropertyInfo : NSObject
@property (nonatomic, assign, readonly) FieldType type;
@property (nonatomic, copy, readonly) NSString * name;
@property (nonatomic, assign, readonly) SEL setter;
@property (nonatomic, assign, readonly) SEL getter;
@end
@implementation PropertyInfo
- (PropertyInfo *)initWithType:(FieldType)type propertyName:(NSString *)property_name {
self = [super init];
if (self) {
_name = property_name.mutableCopy;
_type = type;
_setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[property_name substringToIndex:1].uppercaseString,[property_name substringFromIndex:1]]);
_getter = NSSelectorFromString(property_name);
}
return self;
}
@end
+ (id)querySubModel:(Class)model_class conditions:(NSArray *)conditions queryType:(QueryType)query_type;
id model_object = [model_class new];
//PropertyInfo 为一个model
PropertyInfo * property_info = field_dictionary[field_name];
//setter
NSNumber * value = @(((int64_t (*)(id, SEL))(void *) objc_msgSend)((id)model_object, property_info.getter));
//getter
((void (*)(id, SEL, float))(void *) objc_msgSend)((id)model_object, property_info.setter, value);