字典转模型之KVC和MJExtension底层实现
来源:互联网 发布:遗传算法 排课系统 编辑:程序博客网 时间:2024/05/18 22:43
一 快速生成@property
1 当我们需要用模型去实现一个比较小的功能的时候,由于我们需要对plist文件进行转化成模型,那么很有可能我们拿到的plist文件中的属性很多,但是我们又因为只需要研究一个很小的功能,那么我们可以不需要将plist文件中的数据全部转化为模型数据,我们只需要提取其中的一部分用来实现模型就可以,那么我们怎么做呢?
2 做法:展开某行,然后拷贝该行的item,然后将所有的item折起来,在将拷贝的东西复制到root上即可直接将一整个plist文件改为自己需要处理的文件,用该文件去处理一项特别小的功能.
3 但是由于plist文件中属性太多,如果我们要创建一个模型,那么不得不写这么多属性,首先写这些属性都是无用功,没什么技术含量,那么我们就想,有没有什么办法,可以一次性生成写好的属性,或者我们直接拷贝就可以了.那么,我们就想到了一个方法,通过一个方法,可以快速的将plist文件中的属性生成@property的格式,我们只需要将结果拷贝,往@interface中粘贴就可以了.
4 代码(通过一个分类就可以达到效果,如果需要就直接将分类拷贝到项目中就可以)
//快速生成@property属性- (void)creatPropetyCode{ //创建可变的字符串 NSMutableString *codes = [NSMutableString string]; //由于plist文件外层都是字典,那么我们就遍历字典 [self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull value, BOOL * _Nonnull stop) { //初始化变量,用来接收字符串的 NSString *code = nil; //打印所有的value的类型,就知道BOOL到底是什么类型了. //2016-03-26 23:06:50.867 03-RunTime(字典转模型)[853:40171] __NSCFBoolean NSLog(@"%@",[value class]); //判断value的类型,然后响应的凭借出不同类类型的字符串,满足模型中定义属性的需求 if ([value isKindOfClass:[NSString class]]) { code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSString *%@;",key]; }else if ([value isKindOfClass:NSClassFromString(@"__NSCFBoolean")]){ code = [NSString stringWithFormat:@"@property (nonatomic, strong) BOOL *%@;",key]; }else if ([value isKindOfClass:[NSNumber class]]){ code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSNumber *%@;",key]; }else if ([value isKindOfClass:[NSDictionary class]]){ code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSDictionary *%@;",key]; }else if ([value isKindOfClass:[NSArray class]]){ code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSArray *%@;",key]; } //拼接字符串 [codes appendFormat:@"\n%@\n",code]; }]; //打印出结果 NSLog(@"%@",codes);}//从打印的结果来看,大部分的都能打印出来,但是类型是BOOL的却打印不出来,我们也没法通过判断BOOL的类型来打印,因为BOOL就不是一个类.所以我们必须得想法办知道BOOL的类型.
二 KVC底层实现
1 模型中的KVC方法
//KVC [statusItem setValuesForKeysWithDictionary:dict];
2 问题:KVC底层是怎么实现通过字典对模型中的属性赋值?
2.1 首先我么要明确KVC的使用条件:KVC的使用,必须要保证模型中的属性名要和字典中的key一一对应,否则使用KVC运行时会报错的.
2.2 setValuesForKeysWithDictionary:该方法本质其实就是遍历字典中所有的key,去模型中查找对应的属性,把值给模型属性赋值
3 setValuesForKeysWithDictionary:该方法的底层实现原理:
//遍历 [dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { // 这行代码才是真正给模型的属性赋值 [s setValue:dict[@"source"] forKey:@"source"]; }];
4 遍历字典的内部给属性赋值遵循下面几点条件
/* [s setValue:dict[@"source"] forKey:@"source"]; 1.首先会去模型中查找有没有setSource方法,直接调用set方法 [s setSource:dict[@"source"]]; 2.去模型中查找有没有source属性,source = dict[@"source"] 3.去模型中查找有没有_source属性,_source = dict[@"source"] 4.调用对象的 setValue:forUndefinedKey:直接报错 */
5 很多时候我们不需要plist文件中的所有的属性都有作用,但是我们又想用kvc来实现给模型属性赋值,那么我们有什么办法呢?
5.1 由于我们都知道,如果在plist文件中的属性和模型中的属性并不是一一对应的关系,但是如果我们用KVC运行起来会直接报错,打印出错误的结果是:setValue: forUndefinedKey:那么我们是不是想办法不让这错误提示出来呢.那么我们可以重写系统的这个方法,里面什么都不需要做.这样同样能达到目的.
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{}
三 MJExtension框架的底层实现(一级转化)
MJ框架与KVC的底层实现不同点:
1 KVC是通过遍历字典中的所有key,然后去模型中寻找对应的属性
2 MJ框架是通过先遍历模型中的属性,然后去字典中寻找对应的key,所以用MJ框架的时候,模型中的属性和字典可以不用一一对应,同样能达到给模型赋值的效果.
3 代码:
//返回一个创建好的模型+ (instancetype)modelWithDict:(NSDictionary *)dict{ //创建一个模型 id objc = [[self alloc] init]; int count = 0; /* 方法:获取成员变量列表 参数一:class获取哪个类成员变量列表 参数二:count成员变量总数 */ // 成员变量数组 指向数组第0个元素 Ivar *ivarList = class_copyIvarList(self, &count); // 遍历所有成员变量 for (int i = 0; i < count; i++) { // 获取成员变量 Ivar ivar = ivarList[i]; // 获取成员变量名称(将c转为oc) NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)]; // 成员变量名称转换key(将成员变量前边的"_"截取掉) NSString *key = [ivarName substringFromIndex:1]; // 从字典中取出对应value id value = dict[key]; // 给模型中属性赋值(底层会去找对应的属性和值) [objc setValue:value forKey:key]; } return objc;}
四 附加知识点
1 const与宏的区别
1.1 编译的时刻不一样: 宏:预编译 const:编译
1.2 编译检查:宏不会做编译检查 const会
1.3 宏的好处:宏可以定义函数和方法 const不可以
1.4 宏坏处:大量使用宏,会导致预编译时间过长
2 const作用
2.1 用于修饰右边变量(基本变量,指针变量)
2.2 被const修饰变量只读
2.3 有关const的面试题
int * const p1; // p1:只读 *p1:变量 const int *p2; // p2:变量 *p2:只读 int const *p3; // p3:变量 *p3:只读 int const * const p4; // p4:只读 *p4:只读 const int * const p5; // p5:只读 *p5:只读
3 const在开发当中的使用
3.1 const替换宏,宏:常用字符串或者基本数据定义成宏 -> const
3.2 修饰方法参数,让方法参数只读
4 static和extern
4.1 static:
—–>1> 修饰局部变量,只要被static修饰局部变量,这个局部变量的声明周期就会延长(整个app运行过程中都在),作用域不变
—–>2> 修饰全局变量,只要被static修饰全局变量,这个全局变量只能在当前文件下使用
—–>3> 分配时刻:程序一运行的时候就会分配内存
4.2 extern:
—–>1> 仅仅只用来声明外部全局变量
—–>2> extern不能用来定义变量
5 static和const联合使用
5.1 被static修饰全局变量,全局变量只能在当前文件下使用
5.2 被const修饰,只读.
6 开发中是如何避免重复定义?
做法:只要定义全局变量,都不能再自己的类中定义,一般开发中,我们会搞一个公共的文件来定义全局变量
五 总结
以上就是今天我给大家分享的知识点,很多知识点都写得很详细了,如果有不懂的可以给我留言,谢谢.我明天还会持续更新新的知识点.记得关注哦!!!
1 0
- 字典转模型之KVC和MJExtension底层实现
- MCV中字典转模型的KVC底层实现
- MJExtension 字典转模型
- KVC之快速字典转模型
- iOS-字典转模型 和 kvc
- KVC和runtime字典转模型
- MJExtension 字典转模型高级使用技巧
- IOS 字典模型互转框架 MJExtension
- iOS MJExtension字典转模型高级使用技巧
- KVC简单介绍 -字典转模型,模型转字典
- 使用KVC进行字典转模型
- KVC,字典转模型 & 泛型数组
- MJExtension 2.0 字典转模型再叙 常用的字典转模型使用实例说明
- KVC底层实现
- iOS 底层实现 - KVC
- MJExtension,模型、字典、json数据转换
- MJExtension底层实现原理简单剖析
- MJExtension字典和模型之间相互转换的轻量级框架的使用实例
- 《C++》05 C++ 修饰符类型
- python(1)-简单数据类型
- (二)BeautifulSoup的基本了解使用
- Android IPC 之 AIDL(一)
- 阿里云美国服务器上架设VPN/代理不能访问facebook TW
- 字典转模型之KVC和MJExtension底层实现
- iOS中几种数据持久化方案-转自简书
- HDOJ-----1060简单数学题
- 《C++》06 C++ 存储类
- HDU 5651
- CRCK array 1.5 (easy)
- Linux 每天定时重启
- 从零开始学_JavaScript_系列(一)初步概念、工具选择、简单内容输出、加载js文件
- 提交github常见问题