动态方法决议与消息转发

在Objective-C中,如果向一个对象发送一条该对象无法处理的消息(对应selector不存在),会导致程序crash, 但是,在crash之前,oc的运行时系统会先经过以下两个步骤:

  1. Dynamic Method Resolution
  2. Message Forwarding

1 Dynamic Method Resolution(动态方法决议)

Objective C 提供了一种名为动态方法决议的手段,使得我们可以在运行时动态地为一个 selector 提供实现。我们只要实现 +resolveInstanceMethod: 或 +resolveClassMethod: 方法,并在其中为指定的 selector 提供实现即可(通过调用运行时函数 class_addMethod 来添加),并返回YES,运行时系统会重启一次消息的发送过程,调用动态添加的方法。例如,下面的例子:

void dynamicMethodIMP(id self, SEL _cmd) {
    // implementation ....
}

@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if (aSEL == @selector(resolveThisMethodDynamically)) {
          class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
          return YES;
    }
    return [super resolveInstanceMethod:aSEL];
}
@end

class_addMethod 方法动态的添加新的方法与对应的实现,如果调用了[MyClass resolveThisMethodDynamically],将会转到动态添加的dynamicMethodIMP 方法中。Objective-C的方法本质上是一个至少包含两个参数(id self, SEL _cmd)的C函数,这样,当重启消息发送时,就能在类中找到@selector(dynamicMethodIMP)了。而如果方法返回NO时,将会进入下一步:消息转发(Message Forwarding)

2 Message Forwarding(消息转发)

消息转发分为两步:

首先运行时系统会调用- (id)forwardingTargetForSelector:(SEL)aSelector方法,如果这个方法中返回的不是nil或者self,运行时系统将把消息发送给返回的那个对象。

如果返回的是nil或者self,运行时系统首先会调用- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector方法来获得方法签名,方法签名记录了方法的参数和返回值的信息。

如果-methodSignatureForSelector 返回的是nil, 运行时系统会抛出unrecognized selector exception,程序到这里就结束了。

3 流程图

整个流程可以用下面这张图表示

调用[[YJItem alloc] test],从控制台打印方法的执行顺序如下所示

resolveInstanceMethod:
forwardingTargetForSelector:
methodSignatureForSelector:
resolveInstanceMethod:
doesNotRecognizeSelector:
-[YJItem test]: unrecognized selector sent to instance 0x61800000d5c0

 


Appendix

Objective-C Runtime Programming Guide

Revision History

时间描述
2016-10-14博文完成
2016-10-17添加控制台crash输出

CSDN:http://blog.csdn.net/y550918116j

GitHub:https://github.com/937447974

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值