美文网首页iOS底层知识
Objective-C Runtime(二)动态方法解析和转发

Objective-C Runtime(二)动态方法解析和转发

作者: liuyanhongwl | 来源:发表于2017-12-04 19:33 被阅读30次

Runtime 2 动态方法解析和转发

Objective-C Runtime(一)

  • 简介
  • 对象、类的结构
    • objc_object
    • objc_class
  • 消息传递(Messaging)
    • objc_method
    • objc_msgSend

Objective-C Runtime(二)

  • 动态方法解析和转发
    • 动态方法解析
    • 快速消息转发
    • 标准消息转发
    • 消息转发与多继承
    • 消息转发与代理对象

Objective-C Runtime(三)

  • Method Swizzling
    • class_replaceMethod
    • method_setImplementation
    • method_exchangeImplementations
    • Method Swizzling 的应用
    • Method Swizzling 注意事项

Objective-C Runtime(四)

  • isa swizzling
    • 介绍
    • 应用之KVO
    • 注意

持续更新中...

动态方法解析和转发

当一个对象能接收一个消息时,就会走正常的方法调用流程,也就是上面的消息传递流程。但如果一个对象无法接收指定消息时,又会发生什么事呢?

当向someObject发送某消息,但runtime system在当前类和父类中都找不到对应方法的实现时,runtime system并不会立即报错使程序崩溃,而是依次执行下列步骤:

message_forwarding_1.png

流程:

  • 动态方法解析
  • 快速消息转发
  • 标准消息转发

动态方法解析(Dynamic Method Resolution)

对象在接收到未知的消息时,首先会调用所属类的类方法+resolveInstanceMethod:(实例方法)或者+resolveClassMethod:(类方法)。在这个方法中,我们有机会为该未知消息新增一个”处理方法””。

我们可以在这里添加对该消息的处理方法,并返回YES,则将重新objc_msgSend:

+ (BOOL)resolveInstanceMethod:(SEL)aSEL  
{  
    if (aSEL == @selector(resolveThisMethodDynamically)) {  
          class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");  
          return YES;  
    }  
    return [super resolveInstanceMethod:aSEL];  
} 

快速消息转发

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

- (id)forwardingTargetForSelector:(SEL)aSelector  
{  
    Doctor *doctor = [[Doctor alloc]init];  
    if ([doctor respondsToSelector:aSelector]) {  
        return doctor;  
    }  
    return nil;  
} 

这一步我们只想将消息转发到另一个能处理该消息的对象上。但这一步无法对消息进行处理,如操作消息的参数和返回值。

标准消息转发

如果想要对消息进行处理,就可以在这一步操作消息的参数和返回值,还可以让多个对象响应,甚至把消息吞掉。

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

也就是说如果本类没有能响应的方法,-methodSignatureForSelector:方法本来应该返回nil,需要重写该方法想办法返回需要的签名,好让runtime system可以调用-forwardInvocation:。重写-forwardInvocation:,来对消息进行处理(交给其它对象处理、处理消息参数等)。

需要重写-methodSignatureForSelector:-forwardInvocation:方法:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector  
{  
    NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];  
    if (signature==nil) {  
        signature = [someObj methodSignatureForSelector:aSelector];  
    }  
    NSUInteger argCount = [signature numberOfArguments];  
    for (NSInteger i=0 ; i<argCount ; i++) {  
        //操作参数
    }  
      
    return signature;  
}  
  
- (void)forwardInvocation:(NSInvocation *)anInvocation  
{  
    SEL seletor = [anInvocation selector];  
    if ([someObj respondsToSelector:seletor]) {  
        [anInvocation invokeWithTarget:someObj];  
    }  
      
}  

两种消息转发方式的比较

  • 快速消息转发:简单、快速、但仅能转发给一个对象。
  • 标准消息转发:稍复杂、较慢、但转发操作实现可控,可以实现多对象转发。

消息转发与多继承

转发类似继承,可以用来支持Objective-C 编程的多重继承的某些效果。一个对象通过转发消息来响应消息,该对象似乎是借或者“继承”另一个类中实现的方法。如下图所示:

message_forwarding_2.gif

不过消息转发虽然类似于继承,但NSObject的一些方法还是能区分两者。如-respondsToSelector:-isKindOfClass:只能用于继承体系,而不能用于转发链。便如果我们想让这种消息转发看起来像是继承,则可以重写这些方法。

消息转发与代理对象

转发不仅模仿多重继承,还可以开发轻量级对象代表原来的对象。代理代替原来的对象并传送消息给原来的对象。

苹果给了更为纯净的类NSProxy,专门处理消息转发。

相关文章

  • Objective-C Runtime(二)动态方法解析和转发

    Runtime 2 动态方法解析和转发 Objective-C Runtime(一) 简介 对象、类的结构 obj...

  • Runtime

    定义 runtime 详解文章 1. 消息转发 动态方法解析(方法调用的必经之路) 快速转发(动态解析失败后,指...

  • Runtime-原理

    runtime初探对象与方法的本质runtime-消息发送runtime-动态方法解析runtime-消息转发 r...

  • iOS - Runtime - 概念和方法交换

    runtime的概述runtime的相关概念runtime消息机制消息传递动态方法解析消息转发runtime的作用...

  • iOS面试题总结2018年3月

    一、Runtime的消息转发机制1.动态方法解析 备用接受者3.完整转发 1.动态方法解析对象在接受到未知消息时,...

  • 详解Runtime运行时机制

    引言 简介 与Runtime交互 Runtime术语 消息 动态方法解析 消息转发 健壮的实例变量(Non Fra...

  • iOS 底层 - 名词解析

    目录 前言 名词解析 OC消息传递和转发机制 Runtime runtime动态创建类 Runloop Metho...

  • Runtime之动态方法解析和转发

    前言 在Objective-C中,如果只在头文件中声明了方法,但没有在m文件中实现该方法,如果调用该方法,通常情况...

  • Runtime入门总结

    简介Runtime的基础数据结构消息发送1. 方法调用流程2. 动态方法解析3. 快速转发4. 标准转发API使用...

  • dailyLearning -- runtime

    Runtime 简介 消息传递 消息转发 Runtime 应用 Objective-C 是一门动态语言,它会将一些...

网友评论

    本文标题:Objective-C Runtime(二)动态方法解析和转发

    本文链接:https://www.haomeiwen.com/subject/bjqfixtx.html