『Runtime』详解(一)基础知识

作者:行走少年郎
链接:https://www.jianshu.com/p/633e5d8386a8

1. 什么是 Runtime?

  • OC是一门动态语言,在编译阶段并不知道变量的具体数据类型,也不知道真正的调用函数。runtime运行库就是实现OC运行时的基础。这个库使我们可以在程序运行时动态的创建对象、检查对象,修改类和对象的方法。

2. 消息机制的基本原理

  • 对象方法调用都是类似[receiver selector];的形式。
  • 编译阶段:[receiver selector];方法被编译器转换为:
    objc_msgSend(receiver,selector)(不带参数)
    objc_msgSend(recevier,selector,org1,org2,…)(带参数)
  • 运行时阶段:消息接受者 recevier 寻找对应的 selector。
    1 通过recevier的isa指针找到recevier的Class(类)
    2 在Class(类)的cache(方法缓存)的列表中寻找对应的IMP(方法实现)
    3 如果在 cache(方法缓存) 中没有找到对应的 IMP(方法实现) 的话,就继续在 Class(类) 的 method list(方法列表) 中找对应的 selector,如果找到,填充到 cache(方法缓存) 中,并返回 selector
    4 如果在 Class(类) 中没有找到这个 selector,就继续在它的 superClass(父类)中寻找
    5 一旦找到对应的 selector,直接执行 recevier 对应 selector 方法实现的 IMP(方法实现)
    6 若找不到对应的 selector,消息被转发或者临时向 recevier 添加这个 selector 对应的实现方法,否则就会发生崩溃

3. Runtime 中的概念解析

4. Runtime 消息转发

4.1 消息动态解析

4.2 消息接受者重定向

4.3 消息重定向

5. 消息发送以及转发机制总结

调用 [receiver selector]; 后,进行的流程:
编译阶段:[receiver selector]; 方法被编译器转换为:
objc_msgSend(receiver,selector) (不带参数)
objc_msgSend(recevier,selector,org1,org2,…)(带参数)
运行时阶段:消息接受者 recevier 寻找对应的 selector。
通过 recevier 的 isa 指针 找到 recevier 的 class(类);
在 Class(类) 的 cache(方法缓存) 的散列表中寻找对应的 IMP(方法实现);
如果在 cache(方法缓存) 中没有找到对应的 IMP(方法实现) 的话,就继续在 Class(类) 的 method list(方法列表) 中找对应的 selector,如果找到,填充到 cache(方法缓存) 中,并返回 selector;
如果在 class(类) 中没有找到这个 selector,就继续在它的 superclass(父类)中寻找;
一旦找到对应的 selector,直接执行 recevier 对应 selector 方法实现的 IMP(方法实现)。
若找不到对应的 selector,Runtime 系统进入消息转发机制。
运行时消息转发阶段:
动态解析:通过重写 +resolveInstanceMethod: 或者 +resolveClassMethod:方法,利用 class_addMethod方法添加其他函数实现;
消息接受者重定向:如果上一步添加其他函数实现,可在当前对象中利用 forwardingTargetForSelector: 方法将消息的接受者转发给其他对象;
消息重定向:如果上一步没有返回值为 nil,则利用 methodSignatureForSelector:方法获取函数的参数和返回值类型。
如果 methodSignatureForSelector: 返回了一个 NSMethodSignature 对象(函数签名),Runtime 系统就会创建一个 NSInvocation 对象,并通过 forwardInvocation: 消息通知当前对象,给予此次消息发送最后一次寻找 IMP 的机会。
如果 methodSignatureForSelector: 返回 nil。则 Runtime 系统会发出 doesNotRecognizeSelector: 消息,程序也就崩溃了。

你可能感兴趣的:(『Runtime』详解(一)基础知识)