RunTime实现的反射

    xiaoxiao2021-03-25  78

    Objective-C 中基于RunTime实现的反射 一、反射 反射,一般表现在字符串和Class转换,字符串和内部方法转换,字符串和属性的转换(取值和赋值)。 二、Objective-C中的反射 OC的反射是基于其Runtime实现的。 以执行某个函数为例,我们知道在OC中执行[pyPerson doSomething]函数,实质上是发送了一个消息给Runtime,然后Runtime再根据这个Class的字符串名和这个函数的字符串名,去匹配真正相应的方法的地址,然后再执行的。所以中间我们可以利用字符串去动态的检测,甚至动态的修改(之前说到的Method Swizzling)。 在OC中,很多Runtime的动态特性的接口大致都已经在NSObject.h中声明,可以自己看下源码。  1.字符串和Class转换,及判断 Class __nullable NSClassFromString(NSString *aClassName); -(BOOL)isKindOfClass:(Class)aClass; -(BOOL)isMemberOfClass:(Class)aClass; example: //通过这样的方式获取class Class Person = NSClassFromString(@"PYPerson");   PYPerson *person= [[Person alloc] init];  //判断是否为其子类的对象 PYPerson *person= [[PYPerson alloc] init];  if([personisKindOfClass:[PYStudent class]]){ PYLog(@"person是PYStudent类型或其子类"); }else{ PYLog(@"person不是PYStudent类型或其子类"); } //判断是否是该class的对象if([person isMemberOfClass:[PYStudentclass]]){ PYLog(@"person是PYStudent类型"); }else{ PYLog(@"person不是PYStudent类型"); }  2.字符串和内部方法转换 - (BOOL)respondsToSelector:(SEL)aSelector  判断类型或对象有没有某个方法 + (BOOL)instancesRespondToSelector:(SEL)aSelector; //判断静态方法 - (id)performSelector:(SEL)aSelector  动态调用对象的方法 - (BOOL)conformsToProtocol:(Protocol *)aProtocol; 判断对象是否实现某个Protocol协议 example: //动态生成方法选择器 SEL sel =  NSSelectorFromString(@"setAge:");   //检测是否存在某方法 PYStudent *stu = [[PYStudent alloc]init];   if([stu respondsToSelector:@selector(setAge)]){       PYLog(@"stu 有setAge这个方法");   }else{       PYLog(@"没有");   }   //动态动用方法 PYStudent *stu = [[PYStudent alloc]initAge:1];   int age = [stu performSelector:@selector(age)];   PYLog(@"%i",age);//输出1   //动态调用有参数的方法 [stu  performSelector:@selector(setAge:) withObject:@"2"];  3.字符串和属性的转换 OC中属性的反射通过KVC(Key-Value Coding)机制实现,KVC是一种间接访问对象属性的机制,不直接调用getter 和 setter方法,而使用valueForKey 来替代getter 方法,setValue:forKey来代替setter方法。 具体KVC使用的Example为: PYPersion *persion = [[PYPersion alloc] init]; //不使用KVC persion.name = @"yu" ; //使用KVC的写法 [persion  setValue:@"yu" forKey:@"name"]; 上面是利用KVC访问类里的某个属性,下面利用KVC直接访问类里的类里的某个属性 //不使用KVC PYPersion *persion = [[PYPersion alloc] init]; PYPhone *phone = persion.phone; PYBattery *battery = phone.battery; //使用KVC PYBattery *battery = [persion valueForKeyPath: @"phone.battery" ]; 对于SetValueForKey,需要小心的是,假如类型匹配错误的情况下,编译会通过,但运行会报错

    转载请注明原文地址: https://ju.6miu.com/read-39222.html

    最新回复(0)