前文提到(https://www.jianshu.com/p/588d1d8c3ee1),消息动态方法解析时会重载+(BOOL)resolveInstanceMethod:
和+(BOOL)resolveClassMethod
; 当这两个方法返回NO
时,消息转发机制就会触发.
一 重定向(备援接受者)
在消息转发之前可以通过-(id)fowardingTargetForSelector:(SEL)aSelecto
中把消息转给其它接受者来处理.
新建RedirectionMessageMethod类
@interface RedirectionMessageMethod : NSObject
//被其它接受者处理的方法
- (void)redirectionMethod:(int)temp;
#import "RedirectionMessageMethod.h"
#import "OtherHandelMethod.h"
@implementation RedirectionMessageMethod
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if ([NSStringFromSelector(aSelector) isEqualToString:@"redirectionMethod:"]) {
// 把这个方法转给OtherHandelMethodl类
OtherHandelMethod *otherTar = [OtherHandelMethod new];
return otherTar;
}
return [super forwardingTargetForSelector:aSelector];
}
新建OtherHandelMethod类
#import "OtherHandelMethod.h"
@implementation OtherHandelMethod
- (void)redirectionMethod:(int)temp
{
NSLog(@"实现RedirectionMessageMethod过来的方法redirectionMethod:");
}
运行结果
2018-03-28 10:15:13.051529+0800 OC_Categroy[1015:57719] 实现RedirectionMessageMethod过来的方法redirectionMethod:
二 转发
当消息转发机制触发时,执行forwardInvocation:
;而该方法的参数是NSInvocation
类型的对象(封装了原始的消息和消息参数);通过实现该方法对不能处理的消息做一些默认的处理,也可以将消息转发给其它某个对象来处理.当我们重写forwardInvocation:
方法时,同时也要重写methodSignatureForSelector:
方法,否则抛异常!
forwardInvocation:
方法就像一个不能识别的消息的分发中心,将这些消息转发给不同接收对象。或者它也可以象一个运输站将所有的消息都发送给同一个接收对象。它可以将一个消息翻译成另外一个消息,或者简单的”吃掉“某些消息,因此没有响应也没有错误。forwardInvocation:
方法也可以对不同的消息提供同样的响应,这一切都取决于方法的具体实现。该方法所提供是将不同的对象链接到消息链的能力。
注意: forwardInvocation:
方法只有在消息接收对象中无法正常响应消息时才会被调用。 所以,如果我们希望一个对象将negotiate
消息转发给其它对象,则这个对象不能有negotiate
方法。否则,forwardInvocation:将不可能会被调用。
将上文提到的消息重定向变成完全转发,需要在OtherHandelMethod
创建NSMethodSignature
对象
// 重写methodSignatureForSelector方法 进行完整转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
if ([NSStringFromSelector(aSelector) isEqualToString:@"redirectionMethod:"]) {
NSMethodSignature *sign = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
return sign;
}
return [super methodSignatureForSelector:aSelector];
}
然后实现forwardInvocation:
方法将消息分发给InvocationModel
类
// 消息完整转发给InvocationModel类 InvocationModel里面在实现charge:方法
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
InvocationModel *model = [InvocationModel new];
anInvocation.selector = NSSelectorFromString(@"charge:");
if ([model respondsToSelector:[anInvocation selector]]) {
[anInvocation invokeWithTarget:model];
}else{
[super forwardInvocation:anInvocation];
}
}
新建InvocationModel类
#import "InvocationModel.h"
@implementation InvocationModel
- (void)charge:(int)chareInt
{
NSLog(@"将redirectionMethod方法转发了");
}
运行结果:
2018-03-29 10:38:28.380568+0800 OC_Categroy[921:42779] 将redirectionMethod方法转发了
参考文献::http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/
网友评论