runtime消息转发的处理
代码在执行某一个方法时,代码执行performSelector的动作,在runtime上调用方法objc_msgSend方法(注意类方法的调用是objc_msgSendClass),执行过程如下:
1.objc_msgSend(target, selector)
target为receiver,selector为执行的方法。
Attention!!!
继承自NSObject的类都集成了一个类方法。
+(Bool)resolveInstanceMethod:(SEL)selector的方法,内部实现机制为获取实例对象的方法列表,若有,返回true,若无,返回false。
- 当为true时,进入Event Handle处理事件;
- 当返回为false时,说明没有实现这个方法或者返回为nil,消息进入转发Method Forwarding (消息转发);
2. - (id)forwardingTargetForSelector:(SEL)aSelector
aSelector 待处理的消息,返回一个对象,用于处理消息。
继承自NSObject的类都集成了一个实例方法。
-(id)forwardingTargetForSelector:(SEL)aSelector的方法,当类不识别消息时,执行该方法, 返回一个对象,用于处理aSelector;
- 当为true时,将由返回的object处理事件进入objc_msgSend,继续执行,进入Event Handle处理事件;
- 当返回为false时,说明没有实现这个方法或者返回为nil,使用最后一个挽救的方法,Normal Forwarding(正常转发);
3. - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
消息信号,aSelector 为消息内容。
继承自NSObject的类都集成了一个实例方法。
若是类对于方法有IMP,那么调用父类的该方法就有非nil的返回,若是无IMP,则获取为nil,此时可以把把别的已经实现该方法的类的对象的信号返回,即可实现消息转发;
- 当为true时,说明该类可以处理该方法;
- 当为false时,说明无实现,可自行在子类实现该方法,转发消息;
- 当为false时,且并不转发消息,那么Runtime会抛出donotRecogniseSelector的异常,程序终止运行。
4. - (void)forwardInvocation:(NSInvocation *)anInvocation
invoke NSInvocation,让target执行对应的selector.
在子类中可实现该方法,修改anInvocation的target将消息转发出去。
代码示例
为了学习并补充说明该功能,做了一个demo,展示,代码如下:
1 | #import "ViewController.h" |
我在MViewStage 执行[self performSelector:@selector(doSomething)],但是并没有定义或者实现这个方法,因此我是用如下两种解决方法:
第一种:forwardingTargetForSelector 返回了self.parentViewController;
第二种: 注销掉forwardingTargetForSelector的实现,或者返回为nil,实现了methodSignatureForSelector和forwardInvocation方法,分别返回了self.parentViewController的methodSignatureForSelector,并在forwardInvocation执行了切换target.
以上两种均OK,都可以实现消息的转发。