返回
深入浅出iOS底层 —— 类的加载(下)
IOS
2023-12-12 07:53:22
前言
在前两篇文章中,我们分析了类的加载过程。但在类的加载过程中,不仅仅是类本身的加载,还有分类、类的扩展等的加载。下面我们就来分析一下,分类和类的扩展是怎么加载的。
一、CPP文件分析
1. 分类
首先我们将.m
文件中的分类声明复制到.h
文件中,然后编译.m
文件,此时.h
文件中的分类声明会被编译器忽略,因为分类的实现已经包含在.m
文件中。编译完成后,我们可以看到.o
文件中包含了分类的实现代码。
// MyClass.h
@interface MyClass : NSObject
@end
// MyClass.m
#import "MyClass.h"
@implementation MyClass
- (void)method {
NSLog(@"This is a method in MyClass.");
}
@end
// Category.h
@interface MyClass (Category)
- (void)categoryMethod;
@end
// Category.m
#import "Category.h"
@implementation MyClass (Category)
- (void)categoryMethod {
NSLog(@"This is a method in Category.");
}
@end
编译后的.o
文件内容如下:
// MyClass.o
...
// MyClass的实现代码
...
// Category的实现代码
...
由此可见,分类的实现代码与类本身的实现代码是放在同一个.o
文件中的。
2. 类扩展
类扩展的实现代码与分类的实现代码类似,都是放在同一个.o
文件中。但是,类扩展的实现代码与类本身的实现代码是分开编译的。也就是说,类扩展的实现代码不会影响类本身的实现代码。
// MyClass.h
@interface MyClass : NSObject
@end
// MyClass.m
#import "MyClass.h"
@implementation MyClass
- (void)method {
NSLog(@"This is a method in MyClass.");
}
@end
// Extension.h
@interface MyClass (Extension)
- (void)extensionMethod;
@end
// Extension.m
#import "Extension.h"
@implementation MyClass (Extension)
- (void)extensionMethod {
NSLog(@"This is a method in Extension.");
}
@end
编译后的.o
文件内容如下:
// MyClass.o
// MyClass的实现代码
// Extension.o
// Extension的实现代码
二、运行时分析
1. 分类
分类的加载过程与类的加载过程类似。当一个分类被加载时,首先会创建一个新的类对象,然后将分类的实现代码添加到这个类对象中。这个新的类对象被称为分类类对象。分类类对象的名称与分类的名称相同,但是它的前缀是“_”。例如,分类MyClass (Category)
的分类类对象名称为_MyClass_Category
。
分类类对象被创建后,它会被添加到类的元类对象中。类的元类对象是一个特殊的类对象,它包含了类的信息,例如类的名称、类的父类、类的属性、类的