由于个人水平有限,本博客只是用于个人经验总结,如有纰漏欢迎斧正!
首先创建一个Person类,申明一个方法,run,但是不给于实现,然后创建一个Car类,实现run方法!
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (void)run;
- (void)setText:(NSString *)text;
@end
#import "Person.h"
#import "Car.h"
@implementation Person
@end
#import <Foundation/Foundation.h>
@interface Car : NSObject
@end
#import "Car.h"
@implementation Car
- (void)run{
NSLog(@"%srun",__func__);
}
@end
这时在其他类调用person 的run方法,运行的话会报错unrecognized selector sent to instance!
其具体过程大概是首先会从Person类中去找,看Person中是否有这个方法,如果没有再去Person的父类中寻找,如果再没有就再往上一层找,直到追溯到NSObject,因为NSObject没有父类,此时如果还没有找到,就会进入以下流程:
首先调用person的resolveInstanceMethod:方法!
//在自己的实例方法中寻找,看有没有这个方法,有返回YES,没有返回NO
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if(sel == @selector(run)){
return NO;
}else{
return [super resolveInstanceMethod:sel];
}
}
然后不管返回值为YES还是NO,都会进入到forwardingTargetForSelector:方法,看是否将消息传递给了其他对象
//将消息传递给其他对象,如果为self或者nil则执行下一步!如果为其他对象则传递给该对象
- (id)forwardingTargetForSelector:(SEL)aSelector{
Car *car = [[Car alloc]init];
if (aSelector == @selector(run)) {
return car;
}else{
return [super forwardingTargetForSelector:aSelector];
}
}
如果在这里返回的是其他对象,那么消息将会发送给其他对象,比如上面返回的是Car类的实例对象,那么就会由Car类来接收这个消息,执行run方法!
如果返回的是nil或者self,由于本身没有实现run方法,那么就会进入下一步:
//首先寻找方法签名,如果没有,则会调用系统根类的doesNotRecognizeSelector:方法,不会进入到下面的消息分发.
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSString *sel = NSStringFromSelector(aSelector);
if ([sel isEqualToString:@"run"]) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}else{
return [super methodSignatureForSelector:aSelector];
}
}
//如果上面的方法签名找到了,则会调用这个方法.将消息传递给其他对象,可以传递给多个对象!
- (void)forwardInvocation:(NSInvocation *)anInvocation{
SEL selector = [anInvocation selector];
Car *car = [[Car alloc]init];
if ([car respondsToSelector:selector]) {
[anInvocation invokeWithTarget:car];
}
}
其中上面一个是方法签名, 只要进入了消息转发机制,不管前面两步返回值如何都会在执行前两步后进入到寻找方法签名的方法!方法签名中的v表示返回值为void具体深层的东西尚没有找到详细资料!
下面的是将消息传递给其他对象,其中可以创建多个类进行发送!可以通过这个方法实现伪多继承!