简介

参考资料:

什么是 Runtime

Runtime 顾名思义是运行时的意思,也就是指程序运行的时候。

对于动态语言来说,通常会有很多需要运行时才可以确定的特性,比如:Objective-C 中的消息转发机制、Python 中的变量类型机制等。实现这些动态功能的函数通常被封装成一个库,称作为运行时库。

这里要讲的 Objective-C 的 Runtime 就是 OC 的运行时库。

Objective-C 的 Runtime

Objective-C 有一些动态特性需要运行时库来完成:

  • 类的方法调用、消息转发是间接的:传统的函数一般在编译时就已经把参数信息和函数实现打包到编译后的源码中了;在 OC 中,调用一个实例的方法,所做的是向该实例的指针发送消息,实例在收到消息后,从自身的实现中寻找响应这条消息的方法。

  • 类是动态创建的:持有方法、方法实现、协议等,都是在创建的时候绑定在对象上的;

    简单的可以简化成 Runtime 管理的都是 idid 的本质其实是 objc_object, objc_class 头部其实就是 id, 也就是isa)。

Objective-C 的编译运行结构大致如下:

1
2
3
4
5
6
7
8
9
+--------------------------------------+
| objective-C source code              |
|    +-------------------+-------------+
|    | Framework&Service | Runtime API |
+----+-------------------+-------------+
| compiler                             |
+--------------------------------------+
| Runtime System Library               |
+--------------------------------------+

Objective-C 的代码与 Runtime 的交互发生在以下的三个情况下:

  1. 通过 Objective-C 源代码:所有的 Objective-C 的代码最后都会编译成运行时代码;

  2. 通过 Foundation 框架中 NSObject 类中定义的方法:在 OC 中,除了 NSProxy 以外,所有的类都是 NSObject 的子类,这两个类都遵循了 NSObject 协议。

    因此 NSObject 协议中的方法是所有 OC 对象的公共方法,这个协议定义在了 Public Headers/NSObject.h 这个文件中。

  3. 通过对Runtime 库函数的直接调用:见 官方文档

    不过从 Xcode5 开始,苹果官方不建议直接调用 Runtime 的接口,如果需要代码补全,需要在 Xcode 中开启一个具体的设置 Enable Strict Checking of objc_msgSend Calls