Demo
class_copyPropertyList返回的仅仅是对象类的属性(@property申明的属性),而class_copyIvarList返回类的所有属性和变量(包括在@interface大括号中声明的变量)
/*cls:被添加方法的类
name:可以理解为方法名,这个貌似随便起名,比如我们这里叫guess
imp:实现这个方法的函数
types:一个定义该函数返回值类型和参数类型的字符串,这个具体会在后面讲
class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <nzrm1v#const char *types#>)
class_addMethod([EmptyClass class], @selector(say:), (IMP)say, "i@:@");
其中types参数为"i@:@“,按顺序分别表示:
i:返回值类型int,若是v则表示void
@:参数id(self)
::SEL(_cmd)
@:id(str)
+(void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
Class selfClass = [self class];
SEL oriSel = @selector(sendAction:to:forEvent:);
// 得到类的实例方法 class_getInstanceMethod
Method oriMethod = class_getInstanceMethod(selfClass, oriSel);
SEL cusSel = @selector(mySendAction:to:forEvent:);
Method cusMethod = class_getInstanceMethod(selfClass, cusSel);
// 每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。IMP有点类似函数指针,指向具体的Method实现。
// 我们可以利用 method_exchangeImplementations 来交换2个方法中的IMP,// 我们可以利用 class_replaceMethod 来修改类,
// 我们可以利用 method_setImplementation 来直接设置某个方法的IMP,
// ……
//
// 归根结底,都是偷换了selector的IMP
IMP cusImp = method_getImplementation(cusMethod);
BOOL addsucc = class_addMethod(selfClass, oriSel, cusImp, method_getTypeEncoding(cusMethod));
if (addsucc) {
IMP oriImp = method_getImplementation(oriMethod);
class_replaceMethod(selfClass, cusSel, oriImp, method_getTypeEncoding(oriMethod));
}else{
method_exchangeImplementations(oriMethod, cusMethod);
}
});
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
//2.3 成员属性名 => 字典key
NSString *key = [ivarName substringFromIndex:1];
//2.4 去字典中取出对应value给模型属性赋值
id value = dict[key];
//获取成员属性类型
NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
//二级转换,字典中还有字典,也需要把对应字典转换成模型
//判断下value,是不是字典
if([value isKindOfClass:[NSDictionary class]]&& ![ivarType containsString:@"NS"]){//是字典对象。并且属性名对应类型是自定义类型
//user User
//处理类型字符串 @\"User\" -> User
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"\"" withString:@""];
//自定义对象,并且值是字典
//value:user字典 ->User模型
//获取模型(user)类对象
Class modalClass = NSClassFromString(ivarType);
//字典转模型
if (modalClass) {
//字典转模型
value = [modalClass objectWithDict:value];
}
//字典,user
NSLog(@"%@",key);
}
//三级转换:NSArray中也是字典,把数组中的字典转换成模型
//判断是否是数组
if ([value isKindOfClass:[NSArray class]]) {
//判断对应类有没有实现字典数组转模型数组的协议
if ([self instancesRespondToSelector:@selector(arrayContainModelClass)]) {
//转换成id类型,就能调用任何对象的方法
id idSelf = self;
//获取数组中字典对应的模型
NSString *type = [idSelf arrayContainModelClass][key];
//生成模型
Class classModel = NSClassFromString(type);
NSMutableArray *arrM = [NSMutableArray array];
//遍历字典数组,生成模型数组
for (NSDictionary *dict in value) {
//字典转模型
id model = [classModel objectWithDict:dict];
[arrM addObject:model];
}
//把模型数组赋值给value
value = arrM;
}
}
//2.5KVC字典转模型
if (value) {
[objc setValue:value forKey:key];
}
}
//返回对象
return objc;
}
网友评论