美文网首页
消息转发机制

消息转发机制

作者: Ly梦k | 来源:发表于2018-11-02 13:59 被阅读0次

前言

在上一篇Runtime源码 方法调用的过程中我们了解了消息的响应过程,即

  1. 先缓存查找,若未找到
  2. 接下来查找本类的方法列表查找,若未找到
  3. 则递归继承体系查找父类的方法列表直到NSObject

在第二第三步过程中,如果找到了则响应消息,并填充缓存,缓存是保存在元类上的,如果还找不到,则进入接下来的消息转发流程。

消息转发流程也分为三个步骤,动态解析 -> 前端转发 -> 方法签名转发,流程如下:

消息转发
我们结合一个实例来具体看看传送门:QFMessageForwardDemo

动态解析

第一步,当没找到方法时,你可以通过+ (BOOL)resolveInstanceMethod:(SEL)sel+ (BOOL)resolveClassMethod:(SEL)sel来添加实例方法和类方法

这里我们在ViewController中直接调用了QFPersonrun方法,但是QFPerson并没有实现这个方法,所以动态添加了这个方法。

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    
    if (sel == @selector(run:age:)) {//第一步自己添加方法
        class_addMethod(self, sel, (IMP)newRun, "v@:@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

这个添加一个自定义的方法

void newRun(id self,SEL sel, NSString *str, NSInteger age) {//自定义方法实现
    NSLog(@"---run ok---%@---%ld",str,(long)age);
}

这里用到了runtime的动态添加方法,不熟悉的可以看看这个系列文章的前几篇
,执行结果:

QFMessageForwardDemo[18572:704661] ---run ok---hello---18

前端转发

如果第一步没有动态添加方法,则会进入转发的第二步,前端转发,所谓前端转发即是,本类没有实现这个方法,但是另外的一个类实现了这个方法,那么我们可以直接转发这条消息到另外的类实现调用。这里我们新建QFOtherPerson```` 并且实现- (void)run:(NSString *)name age:(NSInteger)age```方法

- (void)run:(NSString *)name age:(NSInteger)age{
    NSLog(@"%@ 执行了 run name = %@,age = %ld",NSStringFromClass([self class]), name,age);
}

QFPerson的实现文件中,实现下面的方法完成转发

- (id)forwardingTargetForSelector:(SEL)aSelector {
    return [[QFOtherPerson alloc]init];//第二步,前端转发
}

ps:此时要先注释注释掉第一步的动态添加方法

执行结果:

QFMessageForwardDemo[19629:739692] QFOtherPerson 执行了 run name = hello,age = 18

签名转发

第三步,也是最后的机会处理这条消息了,首先生成方法签名:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {//第三步,签名转发
    NSString *methodName = NSStringFromSelector(aSelector);
    if ([methodName isEqualToString:@"run:age:"]) {//是我们需要转发的run方法
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    } else {
        return [super methodSignatureForSelector:aSelector];
    }
}

关于invocation你熟悉的可以看ResponderChain+Strategy+MVVM实现一个优雅的TableView这里面有完整的invocation调用方法的例子,这里就不做粘贴了。

最后调用-forwardInvocation:指定target,完成转发:

- (void)forwardInvocation:(NSInvocation *)anInvocation {//签名转发
    SEL selector = [anInvocation selector];//目标方法

    QFOtherPerson *other = [[QFOtherPerson alloc]init];//转发对象

    if ([other respondsToSelector:selector]) {//目标对象能相应此方法
        [anInvocation invokeWithTarget:other];
    } else {
        return [super forwardInvocation:anInvocation];
    }
}

运行结果:

QFMessageForwardDemo[31317:930989] QFOtherPerson 执行了 run name = hello,age = 18

以上就是方法转发的流程,如果以上三步都没有实现则会崩溃,显示一个很常见的异常- unrecognized selector sent to instance 0x60000001b440'

关于之前的流程请参考:Runtime源码 方法调用的过程

相关文章

  • Runtime

    相关简单介绍 消息机制消息传递机制消息转发机制-动态添加方法消息转发机制-快速转发消息转发机制-慢速转发消息转发机...

  • runtime系列文章总结

    《iOS Runtime详解(消息机制,类元对象,缓存机制,消息转发)》《消息转发机制与Aspects源码解析》《...

  • iOS消息转发机制

    消息转发机制: 消息转发机制是相对于消息传递机制而言的。 1、消息(传递)机制 RunTime简称运行时。就是系统...

  • 《Effective Objective-C 2.0 》 阅读笔

    第12条:理解消息转发机制 1. 消息转发机制 当对象接收到无法解读的消息后,就会启动“消息转发”机制,开发者可经...

  • (十二) [OC高效系列]消息的派发机制

    1.什么是消息转发机制 消息转发机制是在调用未知方法时出现的 消息转发机制让程序员有机会去处理未知方法 消息转发机...

  • 消息转发机制(动态消息转发)

    例子分析 1)在给程序添加消息转发功能以前,必须覆盖两个方法,即methodSignatureForSelecto...

  • 深入理解Object-C消息转发机制

    深入理解Object-C消息转发机制 深入理解Object-C消息转发机制

  • 消息发送机制&消息转发机制

    消息发送机制&消息转发机制 消息发送机制:使用了运行时的方式, 通过SEL快速查找IMP的过程. 消息转发机制:I...

  • 消息转发机制

    为什么说 OC 的动态的 严格来说iOS中不存在方法调用的说法,应该说是消息的传递。消息传递和函数调用的区别就是,...

  • 消息转发机制

    前言 在上一篇Runtime源码 方法调用的过程中我们了解了消息的响应过程,即 先缓存查找,若未找到 接下来查找本...

网友评论

      本文标题:消息转发机制

      本文链接:https://www.haomeiwen.com/subject/ckvwtqtx.html