oc消息转发机制

一、消息转发机制二、动态方法决议与消息转发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]为例:

  1. 通过object的isa指针找到它的class
  2. 在class的method_list中找到foo
  3. 如果class中没找到foo,则继续往他的superclass中查找
  4. 一旦找到foo这个函数,就去执行对应的方法实现(IMP)

如果一直没有找到foo,OC的runtime将继续下面的步骤:

二、动态方法决议与消息转发

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

  1. Dynamic Method Resolution(动态方法决议)
  2. 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; }

  • 消息转发流程图:

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