Runtime的初步认识——消息机制

本文深入探讨Objective-C中的消息机制,解释如何通过“发送消息”而非“调用”来执行对象的方法。通过示例代码展示在Runtime下,方法调用转化为C++的过程,揭示了面向对象到面向过程的转变。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前写过一篇《Runtime的初步认识》,读过的小伙伴们应该对OC中的类与C中的结构体的关系有了一定的了解。这篇文章就先介绍一下OC中的方法是如何“调用”的。这就是OC的另一个机制——消息机制。

OC 的消息机制是指,在外部需要执行某个对象的方法时,使用的方式是“发送消息”而不是“调用”。

在学 Runtime 之前你绝对不理解为什么是发送消息而不是调用。“调用”时确定的,而最终要执行哪段代码是不确定的。
有可能现在还不懂这个确定不确定的到底是什么意思。这个问题暂时可以先留着,我们先看看我们的方法“调用”在runtime转化成C或C++的时候到底变成什么样子了。

首先我们新建一个Mac OS X 命令行工程(这个在我们学习OC之前学习C的时候有可能用到过的)新建Mac OS X 命令行工程
这里创建一个命令行工程完全是为了简单。

这样我们就获得了一个main.m文件

然后我们在main.m文件中写一句最简单的实例化对象的代码

id object = [NSObject alloc];
object = [obj init];

保存一下之后用终端cd到这个文件目录下(此处可以打开终端,输入cd空格之后把那个文件夹拖入终端自动生成路径按回车~)

然后执行clang编译命令把main.m文件编译成C++

clang -rewrite-objc main.m

然后你就可以得到一个 main.cpp 文件,这就是 C++ 文件了。

打开这个文件,到文件的最后,你可以找到你写的 main 函数,看看它有什么内容

id object = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc"));
        object = ((id (*)(id, SEL))(void *)objc_msgSend)((id)object, sel_registerName("init"));

似乎看不太懂,所以要简化一下(去掉一些属性声明,不影响实际逻辑)

id object = objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc"));
object = objc_msgSend(object, sel_registerName("init"));

与OC代码对应就是

id object = [NSObject alloc];
//编译成C++后
id object = objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc"));
object = [object init];
//编译成C++后
object = objc_msgSend(object, sel_registerName("init"));

这里

objc_getClass("NSObject") 通过字符串获取Class

sel_registerName("init") 通过字符串获取方法SEL

objc_msgSend(id, SEL) 消息发送的方法

  • 首先通过一个字符串创建一个类的结构体指针
  • 然后通过一个字符串创建一个类方法的结构体指针
  • 最后向类结构体发送一个消息,得到一个结果。

这就是一个最简单的消息机制,把面向对象变为面向过程。

Runtime的实践——给一个类添加属性(关联对象)
Runtime的实践——方法交换

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值