iOS进阶之路 (十一)分类的加载 详解版本
2023-09-13 20:36:43
在上篇文章中,我们介绍了iOS中的类加载机制,并提到+ load方法是非懒加载类的标志。在这篇文章中,我们将对iOS中的分类加载机制进行深入探究,从底层原理的角度剖析非懒加载类和懒加载类的加载过程,并通过实例代码进行详细演示。
分类加载的本质
分类加载本质上是一种动态方法解析(Dynamic Method Resolution)机制。在Objective-C中,每个类都有一个方法解析表(Method Resolution Table,简称MRT),MRT中保存着该类及其父类所有方法的实现地址。当一个对象调用一个方法时,系统会先在该对象的MRT中查找该方法的实现地址,如果找到,则直接执行该方法;如果找不到,则会沿着该对象的继承链向上查找,直到找到该方法的实现地址为止。
分类的加载过程与普通类的加载过程基本相同,都是通过调用objc_registerClassPair函数将分类注册到系统中。当一个分类被加载时,系统会创建一个新的MRT,并将该分类的方法添加到新的MRT中。然后,系统会将该新的MRT与该分类的父类的MRT合并,形成一个新的MRT。最后,系统会将该新的MRT与该分类的父类的父类的MRT合并,依此类推,直到合并到根类NSObject为止。
非懒加载类和懒加载类的加载过程
非懒加载类:+ load方法是在main函数之前被调用的。这个时候为了能后保证+ load方法能被调用,就必须提前把这个类加载好。
非懒加载类的加载过程如下:
- 当程序启动时,系统会调用dyld_objc_notify_register函数将objc_registerClassPair函数注册为类的加载回调函数。
- 当一个非懒加载类被加载时,系统会调用objc_registerClassPair函数将该类注册到系统中。
- objc_registerClassPair函数会创建一个新的MRT,并将该类的所有方法添加到新的MRT中。
- objc_registerClassPair函数会将该新的MRT与该类的父类的MRT合并,形成一个新的MRT。
- objc_registerClassPair函数会将该新的MRT与该类的父类的父类的MRT合并,依此类推,直到合并到根类NSObject为止。
懒加载类:+ load方法是在第一次使用该类的时候被调用的。
懒加载类的加载过程如下:
- 当程序启动时,系统会调用dyld_objc_notify_register函数将objc_registerClassPair函数注册为类的加载回调函数。
- 当一个懒加载类第一次被使用时,系统会调用objc_registerClassPair函数将该类注册到系统中。
- objc_registerClassPair函数会创建一个新的MRT,并将该类的所有方法添加到新的MRT中。
- objc_registerClassPair函数会将该新的MRT与该类的父类的MRT合并,形成一个新的MRT。
- objc_registerClassPair函数会将该新的MRT与该类的父类的父类的MRT合并,依此类推,直到合并到根类NSObject为止。
实例代码
为了更好地理解iOS中的分类加载机制,我们编写了一个简单的示例代码。在这个示例代码中,我们定义了一个非懒加载类和一个懒加载类,并在main函数中使用这两个类。
// 非懒加载类
@interface NonLazyClass : NSObject
@end
@implementation NonLazyClass
+ (void)load {
NSLog(@"NonLazyClass +load");
}
@end
// 懒加载类
@interface LazyClass : NSObject
@end
@implementation LazyClass
+ (void)load {
NSLog(@"LazyClass +load");
}
@end
int main(int argc, char * argv[]) {
// 使用非懒加载类
[NonLazyClass new];
// 使用懒加载类
[LazyClass new];
return 0;
}
当我们运行这段代码时,控制台会输出以下内容:
NonLazyClass +load
LazyClass +load
从输出结果可以看出,非懒加载类在程序启动时就被加载了,而懒加载类在第一次被使用时才被加载。
总结
通过对iOS中分类加载机制的深入探究,我们了解了分类加载的本质、非懒加载类和懒加载类的加载过程,并通过实例代码进行了详细演示。这些知识对我们理解iOS的底层原理和编写高质量的Objective-C代码非常有帮助。