匿名分类
匿名分类,extension,也叫类扩展,是为了给当前的类扩充私有成员变量、属性或者方法。它有两种实现方式,第一种是写在.m文件中;第二种是实现一个extension的.h文件。
1. .m文件中实现
首先,我们先按照第一种方法实现,给TPerson添加了匿名分类,添加了一个名为extendProp的属性,一个名为extendMethod的方法。
@interface TPerson : NSObject
@property (nonatomic, copy) NSString *name;
- (void)sayHello;
+ (void)sayYo;
@end
#import "TPerson.h"
@interface TPerson()
@property (nonatomic, copy) NSString *extendProp;
- (void)extendMethod;
@end
@implementation TPerson
+ (void)load {
NSLog(@"类-load");
}
- (void)sayHello {
NSLog(@"%s",__func__);
}
+ (void)sayYo {
NSLog(@"%s",__func__);
}
- (void)extendMethod {
NSLog(@"%s",__func__);
}
@end
那么匿名分类的数据是什么时候添加到类中的呢,我们知道类的加载有一个重要的方法:read_images,我们在这个方法中添加以下代码,进行调试:
void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses) {
......
for (EACH_HEADER) {
classref_t *classlist =
_getObjc2NonlazyClassList(hi, &count);
for (i = 0; i < count; i++) {
Class cls = remapClass(classlist[i]);
if (!cls) continue;
const char *cname = cls->nameForLogging();
const char *oname = "TPerson";
// printf("类名 :%s \n",cname);
if (cname && (strcmp(cname, oname) == 0)) {
printf("_read_images - _getObjc2NonlazyClassList 类名 :%s - %p\n",cname,cls);
}
addClassTableEntry(cls);
realizeClassWithoutSwift(cls);
if (cname && (strcmp(cname, oname) == 0)) {
printf("_read_images - _getObjc2NonlazyClassList 类名 :%s - %p\n",cname,cls);
}
}
}
}
在realizeClassWithoutSwift上方的printf的地方设置个断点,进行LLDB调试:

此处可以看到类并没有加载完成,ro中没有数据。
然后在realizeClassWithoutSwift下方的printf的地方设置个断点,进行LLDB调试:

此时,可以看到匿名分类中的方法和属性都已经写入到ro中,上述代码,匿名分类和类是一起在realizeClassWithoutSwift方法中加载的。
2. 写成extension的.h文件
我们创建一个名为TPerson+mExtension.h的文件,文件内容如下,
@interface TPerson ()
@property (nonatomic, copy) NSString *sigleExtProp;
@end
当在TPerson.m中引用这个文件,就可以使用了。
总结
匿名分类是用来扩充类的私有属性、方法、协议的。在编译期,和类一起编译、加载的。其信息也会加载到类的ro中。