iOS runtime 深入浅出之三,objc_msgSend 拾遗杂谈 (7)
2023-10-31 02:41:00
前言
在上一篇文章中,我们探讨了 iOS 底层原理 runtime-object_class 拾遗基础,了解了 arm64 之后 isa 是如何使用联合体存储更多的数据,以及如何自定义和使用联合体。我们还讨论了 objc_class->cache_t cache 是一个缓存最近调用 class 的方法,当缓存剩余空间小于 16 个时,系统就会将其中一些方法从缓存中移除。
在这篇文章中,我们将继续深入探究 iOS runtime,重点关注 objc_msgSend 的工作原理,并探讨如何使用自定义联合体和 objc_class->cache_t cache 来优化应用程序的性能。
objc_msgSend 的工作原理
objc_msgSend 是 Objective-C 中用于发送消息的方法,它在运行时动态解析消息并调用相应的方法。objc_msgSend 的工作原理可以分为以下几个步骤:
- 查找接收者对象的类。
- 在接收者对象的类中查找消息选择器对应的方法。
- 检查方法的访问权限并确保调用者有权访问该方法。
- 为方法的参数分配内存。
- 将参数压入栈中。
- 将接收者对象压入栈中。
- 调用方法。
- 将方法的返回值压入栈中。
- 从栈中弹出参数和接收者对象。
- 返回方法的返回值。
自定义联合体和 objc_class->cache_t cache 的使用
正如我们在上一篇文章中提到的,我们可以通过自定义联合体来扩展 objc_class 结构体,从而存储更多的数据。例如,我们可以定义一个名为 MyClass
的类,并使用一个名为 myData
的联合体来存储一些自定义数据:
@interface MyClass : NSObject {
union {
Class isa;
struct {
unsigned int reserved : 16;
unsigned int bits : 16;
} bits;
} _myData;
}
@property (nonatomic, assign) NSUInteger myData;
@end
在上面的代码中,_myData
联合体包含两个成员:isa
和 bits
。isa
成员指向类的 isa 指针,而 bits
成员是一个包含两个 16 位整数的结构体。我们可以使用 myData
属性来访问和修改联合体中的数据。
我们还可以使用 objc_class->cache_t cache 来缓存最近调用 class 的方法。这可以提高方法调用的性能,因为系统不需要每次都搜索类的方法列表。我们可以使用以下代码来访问和修改 cache:
objc_class->cache_t *cache = objc_getClassCache();
cache
指针指向一个包含多个缓存行的数组,每个缓存行包含一个方法选择器和一个指向方法的指针。我们可以使用以下代码来向缓存中添加一个方法:
objc_setMethodInCache(cache, selector, method);
selector
参数是方法选择器,method
参数是指向方法的指针。
性能优化
我们可以通过自定义联合体和 objc_class->cache_t cache 来优化应用程序的性能。例如,我们可以使用联合体来存储一些经常访问的数据,这样就可以避免多次调用 getter 和 setter 方法。我们还可以使用 cache 来缓存最近调用 class 的方法,这样就可以提高方法调用的性能。
总结
在本文中,我们深入探讨了 iOS runtime 中的 objc_msgSend 的工作原理,并了解了如何使用自定义联合体和 objc_class->cache_t cache 来优化应用程序的性能。这些知识可以帮助我们编写出更高效、更健壮的应用程序。