消息转发流程图
如果类接收到无法处理的消息,会触发消息转发机制,一共有三个步骤,接受者在每一步中均有机会处理消息。步骤越往后,处理消息的代价就越大,所以最好再第一步就处理完。
第一道防线
在类里面实现两个方法来处理未知消息。执行动态方法解析之前,先会判断是否曾经有动态解析。
resolveInstanceMethod
:处理实例方法resolveClassMethod
:处理类方法
我们来看个Demo,先看调用方代码
1 | TestA *testA = [[TestA alloc] init]; |
再来看看TestA的定义。
1 | // TestA.h |
TestA中头文件定义了两个方法,但是没有实现,如果不用消息转发机制处理异常,会导致crash,log想必大家应该很熟悉
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[TestA funcA]: unrecognized selector sent to instance 0x6040000125c0’
实例方法存储在类对象,类方法存储在元类对象,在调用class_addMethod
时,第一个参数需要注意。
第二道防线
第二道防线依赖一个函数forwardingTargetForSelector
。
1 | // 类方法 |
第三道防线
第三道防线有两步
- 调用
methodSignatureForSelector
,获取新的方法签名(返回值类型,参数类型) - 调用
forwardInvocation
,转发消息,
1 | // 方法签名(返回值类型,参数类型) |