runtime运行时机制快速入门

Objective-C 是在 C 语言的基础上扩展了一些面向对象的特性和消息转发机制的动态语言,将编译时、链接时的一些操作都放到运行时去处理。所以 Objective-C 不仅仅需要编译器,还需要 runtime 运行时机制来动态创建类和对象,还有消息的发送和转发。

那么什么是runtime运行时机制呢?

runtime 是一套底层的 C 语言库,我们平时写的 Objective-C 代码在运行过程中其实都是转为 runtime 来执行的,Objective-C 的类转成 runtime 的结构体,Objective-C 的方法转为 runtim 的 objc_msgSend() 函数,可以说 runtime 就是 Objective-C 的操作系统。

本篇文章不会深入讲解 runtime 机制,因为作者也不是大牛。如果本文中有错误之处,请在文章底部留言指出,六阿哥感激不尽!下面来看看 runtime 一些常见用法和示例。

发送消息

在 Objective-C 中调用一个方法,其实就是向对象发送一条 SEL 消息,这也就是 Objective-C 的消息机制。首先导入两个头文件 message.h,在 message.h 中其实已经导入了 runtime.h 。像对象发送消息我们使用 objc_msgSend() 函数,但调用时发现这个函数默认是没有参数的,我们进入 message.h 中发现:

默认是调用下面这个函数

我们将Build Settings -> Apple LLVM 7.0 -Preprocessing -> Enable Strict Checking of objc_msgSend Calls修改为No,再次调用这个方法,就可以传递参数了。首先我们创建一个 Person 类用于测试学习,在这个类中定义 -run 和 +run 方法。

Person.h

Person.m

然后在 ViewController.m 中使用运行时分别调用这两个方法。[Person class] 是获取 Person 类对象,扩展:https://blog.6ag.cn/470.html

ViewController.m

控制台输出:

runtime运行时机制快速入门

获取对象成员列表

通过 runtime 运行时我们可以获取一个类的实例变量列表、属性列表、方法列表、协议列表,下面我们通过两个案例来演示下具体获取方式。首先我们在 Person.h 中添加两个实例变量和两个 property 属性:

Person.h

然后在 ViewController.m 中使用运行时来获取实例变量列表,并打印出每个实例变量的名称。

ViewController.m

控制台输出:

runtime运行时机制快速入门

再使用运行时获取对象的方法列表,并将方法名转为字符串打印输出到控制台。

ViewController.m

控制台输出:

runtime运行时机制快速入门

动态添加对象成员

使用 runtime 可以动态创建对象并为对象添加实例变量和方法,值得注意的是我们不能为已经存在的对象添加实例变量和方法。因为已经存在的对象中的所有成员在类加载 +load 方法中已经加载到内存中,并且不会再改变。这里的动态创建对象指代的是我们动态的创建一个类继承自 Person 类,并为我们动态创建的这个对象添加实例变量、方法等。

ViewController.m

控制器输出:

runtime运行时机制快速入门

继续为这个动态创建的对象添加方法,添加方法。

ViewController.m

控制台输出:

runtime运行时机制快速入门

交换方法的实现

在 Person.m 文件中添加一个 +sleep 方法,并在类加载 +load 时使用 runtime 来替换 +run 方法的实现。为什么要在 +load 方法中替换呢?因为程序运行时 +load 方法会将程序中所有类加载到数据段,而我们不能对已经加载进数据段的类的方法进行修改。

Person.m

在 ViewController.m 文件中调用 -run 方法。

ViewController.m

控制台输出:

runtime运行时机制快速入门

为分类添加成员变量

我们知道在 Category 中只能扩展方法而不能扩展属性,但是使用 runtime 运行时却是可以实现的。那么如何实现?我们来新建一个 Person+Extension 分类,对 Person 类扩展一个属性。

Person+Extension.h

然后直接在 ViewController.m 中使用这个属性。

ViewController.m

然后程序就崩溃了,崩溃原因是没有找到 -setPrice 方法。所以,在 Category 中直接使用 property 不会生成带下划线的成员变量和对应的 set、get 方法。

runtime运行时机制快速入门

我们使用 runtime 运行时来解决这个问题,在 Person+Extension.m 中手动实现。

Person+Extension.m

然后再次执行我们的程序,就不会报错了。控制器输出:

runtime运行时机制快速入门

示例代码下载:https://blog.6ag.cn/demo/runtime.zip

六阿哥

目前评论:2   其中:访客  1   博主  1

  1. avatar eric 1
    • avatar 六阿哥

      @eric

评论加载中...

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: