消息转发机制

RunTime:

1、获取所有的属性列表、方法列表、协议列表

2、方法交换

3、方法拦截调用,容错处理

4、动态添加方法,关联对象分类添加属性objc_setAssociatedObject

消息查找与消息转发机制:

1、从缓存方法列表中查找

2、从方法列表中查找

3、从父类指针所指对象中查找

4、一直没找到,转向拦截调用, 重定向

5、如果没有重写拦截调用的方法,程序报错

+(BOOL)resolveClassMethod:(SEL)sel;

+(BOOL)resolveInstanceMethod:(SEL)sel;

//后两个方法需要转发到其他的类处理

-(id)forwardingTargetForSelector:(SEL)aSelector;

-(void)forwardInvocation:(NSInvocation *)anInvocation;

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector  //方法签名

调用resolveInstanceMethod:方法 (或 resolveClassMethod:)。允许用户在此时为该 Class 动态添加实现。如果有实现了,则调用并返回YES,那么重新开始objc_msgSend流程。这一次对象会响应这个选择器,一般是因为它已经调用过class_addMethod。如果仍没实现,继续下面的动作。

调用forwardingTargetForSelector:方法,尝试找到一个能响应该消息的对象。如果获取到,则直接把消息转发给它,返回非 nil 对象。否则返回 nil ,继续下面的动作。注意,这里不要返回 self ,否则会形成死循环。

调用methodSignatureForSelector:方法,尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给forwardInvocation:。

调用forwardInvocation:方法,将第3步获取到的方法签名包装成 Invocation 传入,如何处理就在这里面了,并返回非nil。

调用doesNotRecognizeSelector: ,默认的实现是抛出异常。如果第3步没能获得一个方法签名,执行该步骤。

上面前4个方法均是模板方法,开发者可以override,由 runtime 来调用。最常见的实现消息转发:就是重写方法3和4,吞掉一个消息或者代理给其他对象都是没问题的

也就是说_objc_msgForward在进行消息转发的过程中会涉及以下这几个方法:

resolveInstanceMethod:方法 (或 resolveClassMethod:)。

forwardingTargetForSelector:方法

methodSignatureForSelector:方法

forwardInvocation:方法

doesNotRecognizeSelector: 方法

你可能感兴趣的:(消息转发机制)