返回
深入剖析 iOS 底层之:类的加载过程(下)
IOS
2023-09-04 19:41:26
分类
在研究对象、类的本质的时候,我们都用 clang 命令将 main.m 转换成 main.cpp 文件查看其本质,分类也不例外,我们使用相同的方法分析。首先我们定义一个分类:
@interface Person (Extension)
- (void)sayHello;
@end
然后我们通过 clang 命令将此文件转换成 C++ 文件:
struct objc_category_t {
Class isa;
Class _class;
const char *name;
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
};
从输出结果中我们可以看到,分类实际上也是一个类,它有一个 isa
指针,指向该分类的元类;有一个 _class
指针,指向该分类所属的类;有一个 name
字符串,表示分类的名称;有一个 instanceMethods
方法列表,表示该分类的实例方法;有一个 classMethods
方法列表,表示该分类的类方法;有一个 protocols
协议列表,表示该分类所遵循的协议;还有一个 instanceProperties
属性列表,表示该分类的实例属性。
分类加载过程
分类的加载过程如下:
- 当一个分类被使用时,系统会首先检查该分类是否已经被加载。如果没有被加载,则会调用
objc_loadClass()
函数加载该分类。 objc_loadClass()
函数会首先检查该分类是否已经被注册。如果没有被注册,则会调用objc_registerClassPair()
函数注册该分类。objc_registerClassPair()
函数会为该分类创建一个元类,并将其添加到元类列表中。- 然后,
objc_registerClassPair()
函数会为该分类创建一个类,并将其添加到类列表中。 - 最后,
objc_loadClass()
函数会将该分类的元类和类返回给调用者。
内存管理与性能优化
分类的内存管理与性能优化与类的内存管理与性能优化基本相同。分类的实例对象也是在堆上分配的,分类的类对象也是在元空间中分配的。分类的实例对象与类的实例对象一样,都需要在使用后手动释放。分类的类对象与类的类对象一样,不需要手动释放。
为了优化分类的性能,我们可以使用以下策略:
- 避免在分类中定义实例变量。实例变量会增加分类的大小,并可能导致性能下降。
- 避免在分类中定义方法。方法也会增加分类的大小,并可能导致性能下降。
- 尽量使用分类来扩展已经存在的类,而不是创建新的类。这可以减少代码的冗余,并提高性能。
总结
分类是一种强大的机制,可以用来扩展已经存在的类。分类的加载过程与类的加载过程基本相同。分类的内存管理与性能优化与类的内存管理与性能优化基本相同。为了优化分类的性能,我们可以使用以下策略:避免在分类中定义实例变量,避免在分类中定义方法,尽量使用分类来扩展已经存在的类,而不是创建新的类。