Runtime(一)Runtime简介

从这篇开始,我们要开始讲述Runtime中的一些主要节点,打通这些节点,我们将能从容应对日常开发中遇到的疑难杂症。

本系列文章同样参考官方文档、MJ老师等资料。

一、Runtime是什么

Objective-C Runtime Programming Guide 首先阐明了runtime:

The Objective-C language defers as many decisions as it can from compile time and link time to runtime.

Objective-C语言,会尽量将决议放到运行的时候,而不是在编译和链接过程。

runtime就是运行时提供的一套机制。那么这个机制具体指的是什么?

  • 从代码角度,这是一套底层的 C 语言 API,平时编写的Objc代码,都是基于它来实现的。
    • 下面的源码编译及后续对API解读,就是基于此进行的说明。
  • 从编译运行看,runtime提供了一系列特性,主要是消息机制保证了Objc具有强大的运行时动态变化的能力。
    • 我们会对这些强大的动态能力,作更详细的解读。

runtime有两个版本: “modern” 和 “legacy”。

在 iOS 和 macOS 10.5 之后的 64 位程序中, Objective-C 2.0 采用的是 modern版的 runtime 系统。而 maxOS 较老的32位程序仍采用 Objective-C 1.0对应的legacy 版本的 runtime 系统。

两个版本最大的区别:当更改一个类的实例变量的布局时,在legacy中你需要重新编译它的子类,而modern就不需要。

获取源码后,粗略观察一下,就会发现objc-runtime-new.hobjc-runtime-old.h头文件,以及\__OBJC2__OBJC2_UNAVAILABLE等。这些就是runtime两个版本中在源码中的体现。

注意:后文阐述的是基于modern版本的内容。

二、 如何与Runtime交互

有三种方式可以与Runtime进行交互:

  • Objective-C 源代码
  • NSObject 方法
  • Runtime 方法

1.1 Objective-C 源代码

大部分情况下,runtime都在后台自动运行,我们通过写Objective-C源代码,就使用了runtime。当编译包含Objective-C的类和方法时,编译器就会生成包含runtime中的数据结构和函数。数据结构中包含了从类、分类、协议中定义的的信息,如:selector、变量等等。

1.2 NSObject方法

Cocoa中绝大部分的类都是继承自NSObejct,都会继承NSObject定义的方法。值得注意的例外是NSProxy类。

基于此,NSObject的很多方法就决定了其他类的行为。

NSObject仅作为一个抽象接口,定义了方法,而没有实现代码。比如description,需要子类重载。

一些NSObject类的方法可以直接查询runtime的信息,从而获得自身的信息。比如classisKindeOfClassrespondsToSelector等方法。

1.3 Runtime方法

Runtime系统是一个共享的library,包含了许多方法和数据结构,地址在/usr/include/objc。其中的很多方法,允许你使用C来重写编译行为,其他的方法是通过NSObject类使用。有了这些方法,我们就可以为runtime系统增加接口,或者工具。

三、编译

3.1 源码哪里来

苹果官方开源站点:https://opensource.apple.com

苹果开源网站:包含苹果开源项目和工具,以及文档。

苹果在线源码

下载-源码文件压缩包

下载-苹果objc源码

3.2 编译

如何编译objc的源码呢?

编译后的代码,新建一个target用来后面测试,如下图:

之后,添加编译后的objc项目:

参考

链接

  1. Objective-C Runtime Programming Guide
  2. 苹果开源网站:包含苹果开源项目和工具,以及文档。
  3. 苹果在线源码
  4. 下载-源码文件压缩包
  5. 下载-苹果objc源码

编译代码

objc4-runtime