消息传递给其他对象
首先,我创建一个我自己的对象PPSMyObject,这个对象中有一个方法logMyInfo,然后我在我们的viewcontroller中来执行这个方法,当然VC里面是没有这个方法的,我肯定需要将这个方法传递给PPSMyObject来处理
forwardingTargetForSelector:
首先,我们在方法forwardingTargetForSelector:中来处理PPSMyObject这个对象很简单,就只有一个方法logMyInfo,而且这个方法是在实现文件中,没有在头文件中声明,大家可以思考一下,消息转发为什么能够直接到实现文件中的方法呢?
#import "PPSMyObject.h"
@implementation PPSMyObject
- (void)logMyInfo{
NSLog(@"myInfo");
}
@end
然后在VC中,我们来执行消息转发,同样执行这个不存在的方法
[self performSelector:@selector(logMyInfo)];
然后在方法forwardingTargetForSelector:中,将这个方法抛给PPSMyObject来处理
- (id)forwardingTargetForSelector:(SEL)aSelector{
if (aSelector == @selector(logMyInfo)) {
PPSMyObject *myObject = [[PPSMyObject alloc] init];
return myObject;
}
NSLog(@"forwardingTargetForSelector");
return [super forwardingTargetForSelector:aSelector];
}
执行后的效果,想想也应该清楚,程序没有崩溃,直接将这个消息传递给了PPSMyObject来处理 除了这一步,我们还有最后一步来处理
methodSignatureForSelector: & forwardInvocation:
通过这两个方法也能最后实现消息的转发
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSLog(@"methodSignatureForSelector");
NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
if ([PPSMyObject instancesRespondToSelector:aSelector]) {
signature = [PPSMyObject instanceMethodSignatureForSelector:aSelector];
}
}
return signature;
}
在此方法中,找到如果PPSMyObject中能够找到方法aSelector,那么就将方法使用PPSMyObject签名 然后在方法forwardInvocation:中,NSInvocation封装了所有的该消息的实现细节,在此方法中实现方法
-(void)forwardInvocation:(NSInvocation *)anInvocation{
NSLog(@"forwardInvocation");
if ([PPSMyObject instancesRespondToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:[[PPSMyObject alloc] init]];
}
}
这样,我们就使用了两种方法,来实现消息的传递
类方法的动态添加
关于类方法的消息转发流程,我查了很久,但是目前也只是查到了在方法resolveClassMethod:中来处理,其他的转发流程我都没有找到,如果有同学了解的,请分享一下
我们之前说了一句,添加一个实例方法,其实是在类中增加一个方法,那么添加一个类方法,就应该是在元类中增加一个方法,因为我们之前讲了类对象其实是一个元类的实例,类比就能够理解到其中的原理
我们还是来看代码吧,一目了然
[[ViewController class] performSelector:@selector(logClassMethod)];
在类中,我执行一个类方法,在这里其实我们可以再聊一下类对象。在方法performSelector:,我们查一下这个其实是一个NSObject的实例方法,那么就说明[ViewController class]返回的是一个实例,我们再去Runtime的开源中看一下这个class方法,在Object.mm文件中这个方法是这样的
+ (id)class
{
return self;
}
返回的是自己 self 这里更是说明了ViewController其实是一个对象实例
好,回过头来,我们接着讲
调用了logClassMethod:方法,但是类中没有这个类方法,在resolveClassMethod:来动态增加
/**
处理类方法
@param sel 需要动态添加的方法 @return 是否已经有可实现的方法
*/
+(BOOL)resolveClassMethod:(SEL)sel{
Class metaClass = objc_getMetaClass(class_getName(self));
IMP imp = [self instanceMethodForSelector:@selector(myClassMethod)];
if (sel == @selector(logClassMethod)) {
class_addMethod(metaClass, sel,imp , "v@:");
return YES;
}
return [super resolveClassMethod:sel];
}
- (void)myClassMethod{
NSLog(@"我的动态类方法");
}