runtime的黑魔法
要说明runtime,首先要明白objc这门语言,是基于C的封装.真是因为runtime,objc才有了面对对象的特性.
也就说,所有objc的语言,在运行时都会转换成C.
也是基于这样的特性,runtime可以做很多不可思议的事情.比如动态添加成员变量,函数等等.
User *usr = [[User alloc] init]; NSLog(@"%@",usr.description); unsigned int count = 0; Ivar *members = class_copyIvarList([User class] , &count); for (int i = 0; i<count ; i++) { Ivar var = members[i]; const char *memName = ivar_getName(var); const char *memType = ivar_getTypeEncoding(var); NSLog(@"%s type:%s", memName, memType); } //值修改 Ivar name = members[0]; object_setIvar(usr, name, @"王三蛋"); NSLog(@"object_setIvar修改成员变量Name后的值:%@",usr.description); class_addMethod([User class], @selector(method:), (IMP)addingFunc, "i@:i@"); //通过class_addMethod 动态添加函数 unsigned int FuncCount = 0; Method *membersFuncs = class_copyMethodList([User class], &FuncCount); //遍历已有函数名 for (int i = 0 ; i< FuncCount; i++) { SEL Met = method_getName(membersFuncs[i]); NSString *MetName = [NSString stringWithCString:sel_getName(Met) encoding:NSUTF8StringEncoding]; NSLog(@"User的函数:%@",MetName); } objc_msgSend(usr,@selector(method:),@"动态添加的函数");
int addingFunc(id self,SEL _cmd,NSString *str) { NSLog(@"Added Func,%@",str); return 10; }
给出一个model转换的
// // NSObject+ModelHandle.h // MVVM // // Created by M on 16/3/3. // Copyright © 2016年 Meng. All rights reserved. // #import <Foundation/Foundation.h> @interface NSObject (ModelHandle) +(instancetype)ModelWithDict:(NSDictionary*)dict; @end
// // NSObject+ModelHandle.m // MVVM // // Created by M on 16/3/3. // Copyright © 2016年 Meng. All rights reserved. // #import "NSObject+ModelHandle.h" #import <objc/runtime.h> @implementation NSObject (ModelHandle) +(instancetype)ModelWithDict:(NSDictionary*)dict { id obj = [self new]; for (NSString *propertyName in [self GetProperList]) { if (dict[propertyName]) { [obj setValue:dict[propertyName] forKey:propertyName]; } } return obj; } +(NSArray*)GetProperList { unsigned int count = 0; objc_property_t *propertyList = class_copyPropertyList([self class], &count);//获取class里的属性. NSMutableArray *arr = [NSMutableArray array]; for (int i = 0 ; i<count; i++) { objc_property_t property = propertyList[i]; const char *CharName = property_getName(property); NSString *StrName = [[NSString alloc] initWithUTF8String:CharName]; [arr addObject:StrName]; } free(propertyList);//释放 return arr.copy; } @end
直接在相应的model的头文件里引入 #import "NSObject+ModelHandle.h"
Model *m = [Model ModelWithDict:Dict[@"result"]];
相比 setValuesForKeysWithDictionary, 此函数对数据的检查不是那么严格.