返回

iOS进阶之路 (十一)分类的加载 详解版本

IOS

在上篇文章中,我们介绍了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方法能被调用,就必须提前把这个类加载好。

非懒加载类的加载过程如下:

  1. 当程序启动时,系统会调用dyld_objc_notify_register函数将objc_registerClassPair函数注册为类的加载回调函数。
  2. 当一个非懒加载类被加载时,系统会调用objc_registerClassPair函数将该类注册到系统中。
  3. objc_registerClassPair函数会创建一个新的MRT,并将该类的所有方法添加到新的MRT中。
  4. objc_registerClassPair函数会将该新的MRT与该类的父类的MRT合并,形成一个新的MRT。
  5. objc_registerClassPair函数会将该新的MRT与该类的父类的父类的MRT合并,依此类推,直到合并到根类NSObject为止。

懒加载类:+ load方法是在第一次使用该类的时候被调用的。

懒加载类的加载过程如下:

  1. 当程序启动时,系统会调用dyld_objc_notify_register函数将objc_registerClassPair函数注册为类的加载回调函数。
  2. 当一个懒加载类第一次被使用时,系统会调用objc_registerClassPair函数将该类注册到系统中。
  3. objc_registerClassPair函数会创建一个新的MRT,并将该类的所有方法添加到新的MRT中。
  4. objc_registerClassPair函数会将该新的MRT与该类的父类的MRT合并,形成一个新的MRT。
  5. 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代码非常有帮助。