objc_msgsend学习
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个版本(前面可以是加号+,也可以是减号-)上一篇
lldb积累
下一篇
iOS动调入门
Loading...