Runtime 理解

2018-03-24  本文已影响0人  开发者zhang

Runtime


Runtime 就是去解决如何在运行时期找到调用方法。

(OC 是一门动态语言,函数调用变成了消息发送,在编译期不能知道要调用哪个函数)

对于实例变量有如下的思路:

instance -> class -> method -> SEL -> IMP -> 实现函数

重点:

描述了对象的内存布局

SEL 与 IMP


SEL 可以将其理解为方法的 ID。
IMP 可以理解为函数指针,指向了最终的实现。

OC 中不支持函数重载原因:就是因为一个类的方法列表中不能存在两个相同的 SEL 。

但是多个方法却可以在不同的类中有一个相同的 SEL,不同类的实例对象执行相同的 SEL 时,会在各自的方法列表中去根据 SEL 去寻找自己对应的IMP,这使得OC可以支持函数重写

消息传递机制

如下用于描述 objc_msgSend 函数的调用流程

1.检测 SEL 是否应该被忽略;
2.检测发送的 target 是否为 nil ,如果是则忽略该消息;

  1. 如果还没找到则进入消息动态解析过程

动态消息解析过程

动态消息解析

如下用于描述动态消息解析的流程:

  1. 通过 resolveInstanceMethod 得知方法是否为动态添加,YES则通过 class_addMethod 动态添加方法,处理消息,否则进入下一步。(dynamic 属性就与这个过程有关,当一个属性声明为 dynamic 时 就是告诉编译器:开发者一定会添加 setter/getter 的实现,而编译时不用自动生成。)

  2. 这步会进入 forwardingTargetForSelector 用于指定哪个对象来响应消息。如果返回nil 则进入第三步。(这种方式把消息原封不动地转发给目标对象,有着比较高的效率。如果不能自己的类里面找到替代方法,可以重载这个方法,然后把消息转给其他的对象。)

  3. 这步调用 methodSignatureForSelector 进行方法签名,这可以将函数的参数类型和返回值封装。(如果返回 nil 说明消息无法处理并报错 unrecognized selector sent to instance,如果返回 methodSignature,则进入 forwardInvocation )在forwardInvocation这里可以修改实现方法,修改响应对象等(如果方法调用成功,则结束。如果依然不能正确响应消息,则报错 unrecognized selector sent to instance.)

(可以利用 2、3 中的步骤实现对接受消息对象的转移,可以实现“多重继承”的效果。)


参考:Objective-C Runtime

上一篇 下一篇

猜你喜欢

热点阅读