一、消息转发机制二、动态方法决议与消息转发Dynamic Method Resolution(动态方法决议)Message Forwarding (消息转发)三、实现多重代理
一、消息转发机制
在OC中,调用一个对象的方法,实际上是给对象发了一条消息,在编译Objective-C函数调用的语法时,会被翻译成一个C的函数调用:objc_msgSend(),例如:
[array insertObject:foo atIndex:2];
//会被翻译成:
objc_msgSend(array, @selector(insertObject:atIndex), foo, 2);
复制代码
以[object foo]为例:
- 通过object的isa指针找到它的class
- 在class的method_list中找到foo
- 如果class中没找到foo,则继续往他的superclass中查找
- 一旦找到foo这个函数,就去执行对应的方法实现(IMP)
如果一直没有找到foo,OC的runtime将继续下面的步骤:
二、动态方法决议与消息转发
在oc中,如果向一个对象发送一条该对象无法处理的消息(对应selector不存在),会导致程序crash, 但是,在crash之前,oc的运行时系统会先经过以下两个步骤:
- Dynamic Method Resolution(动态方法决议)
- Message Forwarding(消息转发)
Dynamic Method Resolution(动态方法决议)
让我们可以在程序运行时动态的为一个selector提供实现,如果我们添加了函数的实现,并返回YES,运行时系统会重启一次消息的发送过程,调用动态添加的方法
-
调用实例方法:- (BOOL)resolveInstanceMethod:(SEL)sel
-
调用类方法:+ (BOOL)resolveClassMethod:(SEL)sel
- (BOOL)resolveInstanceMethod:(SEL)sel{ if (sel == @selector(foo)) { class_addMethod([self class], sel, (IMP)dynamicMethodIMP, "V@:"); return YES; } return [super resolveInstanceMethod:sel]; } void dynamicMethodIMP(id self, SEL _cmd){ NSLog(@"%s", PRETTY_FUNCTION); }
class_addMethod(Class cls, SEL name, IMP imp, const char *types) ===> 动态添加方法
const char *types:
”v@:”这是一个void类型的方法,没有参数传入
“i@:”这是一个int类型的方法,没有参数传入。
”i@:@”这是一个int类型的方法,有一个参数传入。==> ''i@:*''
如果方法返回NO时,将会进入下一步:
Message Forwarding (消息转发)
-
先通 SEL查找:先调用:- (id)forwardingTargetForSelector:(SEL)aSelector ,通过aSelector进行查找方法名,返回对象。 ### ProxyDispatcher.h
@interface ProxyDispatcher : NSObject - (void)Func; @end ### ProxyDispatcher.m - (id)forwardingTargetForSelector:(SEL)aSelector{ if (aSelector == @selector(Func)) { return [DispatcherObject new]; } return nil; } ### DispatcherObject.m - (void)Func{ NSLog(@"%s", __PRETTY_FUNCTION__); } 复制代码
-
后通过 签名查找: - (NSMethodSignature )methodSignatureForSelector:(SEL)aSelector *SEL查找失败(返回nil或self) - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{ NSMethodSignature methodSignature = [super methodSignatureForSelector:aSelector]; if (!methodSignature) { methodSignature = [NSMethodSignature signatureWithObjCTypes:"v@:"]; } return methodSignature; }
-
消息转发流程图: