Ivar *ivars = class_copyIvarList([self class], &count); // 反归档时调用 -(instancetype)initWithCoder:(NSCoder *)aDecoder { // self = [super init]; self = [self init]; if (self) { // 若直接采用一般的方法 :----- 属性赋值 // // self.name = [aDecoder decodeObjectForKey:@"name"]; // self.gender = [aDecoder decodeObjectForKey:@"gender"]; // self.age = [aDecoder decodeIntegerForKey:@"age"]; // self.hobby = [aDecoder decodeObjectForKey:@"hobby"]; // self.nickName = [aDecoder decodeObjectForKey:@"nickName"]; // 使用 Runtime 进行反归档处理 unsigned int ivarCount = 0; Ivar * ivarArray = class_copyIvarList([self class], &ivarCount); for (int i = 0; i < ivarCount; i++) { NSString * varName =[NSString stringWithUTF8String:ivar_getName(ivarArray[i])]; id value = [aDecoder decodeObjectForKey:varName]; [self setValue:value forKey:varName]; } free(ivarArray); } return self; } // 归档时调用 -(void)encodeWithCoder:(NSCoder *)aCoder { // [aCoder encodeObject:self.name forKey:@"name"]; // // [aCoder encodeObject:self.gender forKey:@"gender"]; // // [aCoder encodeInteger:self.age forKey:@"age"]; // // [aCoder encodeObject:self.hobby forKey:@"hobby"]; // // [aCoder encodeObject:self.nickName forKey:@"nickName"]; unsigned int ivarCount = 0; Ivar * ivarArray = class_copyIvarList([self class], &ivarCount); // 使用KVC进行取值在归档encode for (int i = 0; i < ivarCount; i++) { // C 语言的字符串转换成NSString NSString * varName = [NSString stringWithUTF8String:ivar_getName(ivarArray[i])]; // 使用KVC 取值 再编码 id value =[self valueForKey:varName]; // 归档 [aCoder encodeObject:value forKey:varName]; } } // 对P2进行归档 NSData * p2Data = [NSKeyedArchiver archivedDataWithRootObject:p2]; // NSLog(@"%@",p2Data); // 进行反归档 转换成对象 Person * p3 = [NSKeyedUnarchiver unarchiveObjectWithData:p2Data]; // NSLog(@"%@",p3.name);
RunTime 的归档反归档适用于归档对象属性较多的情况,可以减少代码量,逻辑更清晰。这种方式一般来说用的比较多,除此之外一些基本的使用方法也是比较常用的,比如说:
1、 动态的为某个类添加属性/方法, 修改属性值/方法
2 、遍历一个类的所有成员变量(属性)/所有方法 那么就这两种方式给出具体的代码实现 :
首先是 动态的为某个类添加属性/方法, 修改属性值/方法
//使用运行时需要导入头文件 #import <objc/objc-runtime.h> //或者直接引入: #include <objc/runtime.h> #include <objc/message.h> Method methodA = class_getInstanceMethod([self class], @selector(testA)); Method methodB = class_getInstanceMethod([self class], @selector(testB)); // 交换AB的方法实现 method_exchangeImplementations(methodA, methodB);
// 实例变量的个数 unsigned int ivarCount = 0; Ivar * ivaArray = class_copyIvarList([类名 class], &ivarCount); for (int i = 0; i < ivarCount; i++) { Ivar var = ivaArray[i]; // 输出实例变量的名称和类型 NSLog(@"%s,%s",ivar_getName(var),ivar_getTypeEncoding(var)); }// 释放指针 free(ivaArray);
获取某个类中的所有的实例方法:
unsigned int methodCount = 0; Method * methodArray = class_copyMethodList([Person class], &methodCount); for (int i = 0; i < methodCount; i++) { Method m = methodArray [i]; // 输出方法的名字和方法的类型编码 NSLog(@"%s,%s",sel_getName(method_getName(m)),method_getTypeEncoding(m)); }
其实Runtime的消息驱动机制是和常见的,除此之外还有动态绑定,具体的动态绑定有两个重要的方法,代码写的很详细:
// 动态绑定 +(BOOL)resolveClassMethod:(SEL)sel { // 输出 方法名 和所在的行数 NSLog(@"%s,%d",__FUNCTION__,__LINE__); // 定义block添加类方法 void (^resolveClassBlock)(id,SEL) = ^(id receiver,SEL objc_cmd){ NSLog(@"%s,类的方法未实现,执行此段",sel_getName(objc_cmd)); }; if (sel == @selector(heiheihei)) { // 调用block IMP blockIMP = imp_implementationWithBlock(resolveClassBlock); // 添加一个类方法 class_addMethod(object_getClass([self class]), sel, blockIMP, "v@:"); } return [super resolveClassMethod:sel]; } // 动态绑定 +(BOOL)resolveInstanceMethod:(SEL)sel { NSLog(@"%s,%d",__FUNCTION__,__LINE__); // 定义block添加实例方法 // 接受者 选标 void(^resolveBlock)(id , SEL) = ^(id receiver, SEL objc_cmd) { NSLog(@"%s,实例方法未实现,会执行此处代码。",sel_getName(objc_cmd)); }; if (sel == @selector(aaacccddd)) { // 获取实现的bolck的地址 IMP blockIMP = imp_implementationWithBlock(resolveBlock); // 第四个参数函数的类型 class_addMethod([self class], sel, blockIMP, "v@:"); } return [super resolveInstanceMethod:sel]; }
//得到方法的签名 -(NSMethodSignature * )methodSignatureForSelector:(SEL)aSelector { NSMethodSignature * sig = [super methodSignatureForSelector:aSelector]; if (!sig) { WS * ws = [[WS alloc]init]; sig = [ws methodSignatureForSelector:aSelector]; } return sig; } -(void)forwardInvocation:(NSInvocation *)anInvocation { // 方法自动执行 对消息进行转发 // 如果 本类调用 study 时 则要对方法进行转发 if (anInvocation.selector == @selector(study)) { [anInvocation invokeWithTarget:[WS new]]; } } [p2 performSelector:@selector(study)];
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. UIApplication *thisApp = [UIApplication sharedApplication]; Ivar statusVar = class_getInstanceVariable([thisApp class], "_statusBar"); id statusBar = object_getIvar(thisApp, statusVar); Ivar statusBackViewVar = class_getInstanceVariable([statusBar class], "_foregroundView"); id statusBackView = object_getIvar(statusBar, statusBackViewVar); NSArray *viewArray = [statusBackView subviews]; UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 3, 43, 15)]; imageView.backgroundColor = [UIColor whiteColor]; imageView.image = [UIImage imageNamed:@"替换成自己喜欢的图片"]; [viewArray[0] addSubview:imageView]; return YES; }