type
status
date
slug
tags
summary
category
icon
password
id 是一种动态类型,表示一个指向任何对象的指针。
- 特点:
- 动态性:在编译时不知道具体的类类型,只有在运行时才知道。
- 方便:允许编写更加通用和灵活的代码,可以指向任何对象,而不需要显式声明类型。
- 安全性:由于
id类型的动态性,编译器不能在编译时检查类型安全,可能会导致运行时错误。
SEL 是一个数据类型,表示一个选择器(selector),即方法的名称。
- 特点:
- 方法标识符:选择器本质上是方法的唯一标识符,可以用来动态调用方法。
- 高效性:选择器通常是由编译器生成的独一无二的标识符,查找速度快。
- 动态调用:配合
@selector语法和NSSelectorFromString函数,可以在运行时动态调用方法。
id 和 SEL 的应用
- 动态方法调用:
id类型可以指向任何对象,而SEL类型可以表示任何方法,这使得动态方法调用成为可能。
- 消息转发机制: 在 Objective-C 中,如果一个对象接收到一个它无法响应的消息,它会将该消息转发给其他对象,这个过程会涉及到
id和SEL类型。
objc_msgSend 是 Objective-C 运行时最核心的函数之一,用于向对象发送消息(即调用方法)。了解它的参数、使用方法以及返回值对于深入理解 Objective-C 的消息机制至关重要。以下是对 objc_msgSend 的详细解释:objc_msgSend 的参数
self: 这个参数是接收消息的对象。它是一个指向对象实例的指针。
op(selector): 这个参数是一个选择器,表示要调用的方法。它是SEL类型,通常由@selector语法或者NSSelectorFromString函数生成。
- 可选参数: 从第三个参数开始,是传递给方法的实际参数。根据方法的签名,这些参数的数量和类型可以变化。
示例代码
假设有一个简单的 Objective-C 类
MyClass,其中有一个方法 - (void)myMethodWithArg:(int)arg;,我们可以用 objc_msgSend 发送消息来调用这个方法。- 定义类和方法:
- 使用
objc_msgSend调用方法:
objc_msgSend 的返回值
objc_msgSend 的返回值类型取决于被调用的方法的返回类型。在调用 objc_msgSend 时,必须正确地转换返回值类型。示例
假设我们有一个返回值类型为
int 的方法 - (int)sumWithA:(int)a b:(int)b;:我们可以使用
objc_msgSend 调用这个方法并获取返回值:注意事项
- 类型转换: 使用
objc_msgSend时需要进行正确的类型转换。因为它是一个可变参数函数,并且返回类型不确定,必须根据实际情况进行强制类型转换。
- 64位架构: 在64位架构上,
objc_msgSend的一些变体如objc_msgSend_stret(用于返回结构体)以及objc_msgSend_fpret(用于返回浮点数)在某些情况下可能需要。
- 性能考虑: 虽然
objc_msgSend提供了强大的动态调用能力,但频繁使用可能会影响性能。在大多数情况下,直接调用方法更高效。
总结
objc_msgSend 是 Objective-C 运行时消息传递机制的核心,它通过 id(对象)和 SEL(选择器)来实现动态方法调用。正确理解它的参数、返回值以及使用方法对深入掌握 Objective-C 编程至关重要。在实际开发中,尽量使用编译器提供的语法糖来发送消息,只有在特殊情况下才直接使用 objc_msgSend。执行流程
- 消息发送
- 动态方法解析
- 消息转发
消息发送

- 如果是从
class_rw_t中查找方法 - 已经排序的,二分查找
- 没有排序的,遍历查找
- receiver通过isa指针找到receiverClass
- receiverClass通过superclass指针找到superClass
动态方法解析

动态解析过后,会重新走“消息发送”的流程
消息转发

如果
动态方法解析阶段没有处理,回来到消息转发阶段首先来到
forwardingTargetForSelector:方法,该方法中可以重新返回一个消息接收者,程序将会重新执行objc_msgSend()方法,此时消息时发送给新的接受者如果forwardingTargetForSelector:方法没有处理,会来到methodSignatureForSelector:方法,该方法可以返回一个方法签名,返回后,程序会继续调用forwardInvocation:方法。如果methodSignatureForSelector:方法也没处理,程序就抛出异常在forwardInvocation:方法中,开发者可以自定义任何逻辑以上方法都有对象方法、类方法2个版本(前面可以是加号+,也可以是减号-)- 作者:moyaoxue
- 链接:https://moyaoxue.de/article/14425ac9-6ea8-80a6-833b-d32cde81dbcc
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

