使用运行时实现字典转模型和关联对象objc_get/setAssociatedObject()
创建一个类Person,重写它的description方法,打印出它的属性值。
XZPerson.m
@implementation XZPerson
- (NSString
*)description {
NSArray *keys =
@[@"name",@"age",@"weight",@"sex"];
return [self
dictionaryWithValuesForKeys:keys].description;
}
@end
NSObject+XZRuntime.h
#import
<Foundation/Foundation.h>
@interface NSObject (XZRuntime)
//
获取类的属性列表
// @return
类的属性列表数组
+ (NSArray
*)xz_objcProperties;
//
给定一个字典,创建 self
类对应的对象
// @param dict
字典 @return
对象
+ (instancetype)xz_objWithDic:(NSDictionary
*)dict;
@end
NSObject+XZRuntime.m
#import
"NSObject+XZRuntime.h"
#import
<objc/runtime.h>
@implementation NSObject (XZRuntime)
//
所有字典转模型框架的核心算法 //
运行时字典转模型的基本方法的实现
+ (instancetype)xz_objWithDic:(NSDictionary
*)dict {
//
实例化对象
id object = [[self
alloc]
init];
//
使用字典,设置对象信息
// 1>获得
self 的属性列表
NSArray *proList = [self
xz_objcProperties];
// 2>遍历字典
[dict
enumerateKeysAndObjectsUsingBlock:^(id
_Nonnull key,
id
_Nonnull obj,
BOOL *
_Nonnull stop) {
NSLog(@"key
%@ ---- value %@",key,obj);
// 3>判断
key 是否存在 proList
中
if ([proList
containsObject:key]) {
//
说明属性存在,可以使用 ‘KVC’
设置数值
[object
setValue:obj
forKey:key];
}
}];
return object;
}
const
char *kPropertiesListKey =
"CZPropertiesListKey";
+ (NSArray
*)xz_objcProperties {
//
因为属性列表在运行的过程中不会改变,所以使用运行时关联对象,提高效率
//
①、从‘关联对象’中获取对象属性,如果有,直接返回!
/**
获取关联对象 --
动态添加的属性
参数1:对象:self
参数2:动态属性的
key
返回值:动态添加的‘属性值’
id
*/
NSArray *ptyList =
objc_getAssociatedObject(self,
kPropertiesListKey);
if (ptyList !=
nil) {
return ptyList;
}
//
使用运行时获取对象的属性数组
// class_copyIvarList Ivar
成员变量
// class_copyPropertyList Property
属性
// class_copyMethodList Method
方法
// class_copyProtocolList Protocol
协议
//
参数一:要获取的类
参数二:类属性的个数指针
//
返回值:所有属性的'数组',C语言中,数组的名字,就是指向第一个元素的地址
unsigned
int outCount =
0;
//
调用运行时方法,取得类的属性列表
objc_property_t *proList =
class_copyPropertyList([self
class], &outCount);
NSLog(@"属性列表的数量
%d",outCount);
NSMutableArray *array = [NSMutableArray
array];
//
遍历所有的属性
for (unsigned
int i =
0; i < outCount; i++) {
//1.从数组中取得属性
C语言的结构体指针,通常不需要'*'
objc_property_t pty = proList[i];
// 2.从pty中获得属性的名称
const
char *cName =
property_getName(pty);
//
将C语言字符串转化成OC字符串
NSString *name = [NSString
stringWithCString:cName
encoding:NSUTF8StringEncoding];
// 3.属性名称添加到数组
[array
addObject:name];
}
// retain/create/copy
需要 release,点击option
+ click查看
//
释放数组
free(proList);
//
②、到此为止,对象的属性数组已经获取完毕,利用关联对象,动态添加属性
/**
参数
1.对象
self [OC 中 class
也是一个特殊的对象]
2.动态添加的属性的
key,获取值的时候也使用
3.动态添加的属性值
4.对象的引用关系
*/
objc_setAssociatedObject(self,
kPropertiesListKey, array.copy,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return array.copy;
}
@end
XZRunTimeController.m
//
字典转模型
XZPerson *person = [XZPerson
xz_objWithDic:@{
@"name":@"zhangsan",
@"age":@18,
@"sex":@"female",
@"height":@1.8,
@"weight":@100,
}];