「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。
这个地方又会牵扯到几种情况:分类的懒加载和非懒加载,类的懒加载和非懒加载。
区分懒加载和非懒加载,按苹果的意思就是实现了+load方法的类/分类是非懒加载,否则是懒加载
这就会产生4种情况,我们一种一种的来看。
老规矩,先创建个Person类,再创建个Person+HJJJJJ分类
分类添加2方法
-(void)sayYes;
-(void)sayNo;
1. 非懒加载类,非懒加载分类。
通过realizeClassWithoutSwift一直往后走 ,最终走到attachCategories,附加分类的东西。
在方法内部增加 断点,通过分类名字来断。
const char *tempChar;
tempChar = cls->nameForLogging();
if (strcmp(tempChar, "Person")==0) {
}
/// 依次读取每一个category,将其methods,property,protocol添加到mlists,proplist,protolist中存储
for (uint32_t i = 0; i < cats_count; i++) {
auto& entry = cats_list[i];
method_list_t *mlist = entry.cat->methodsForMeta(isMeta);
//printf("22-%s\n",entry.cat->name);
if (mlist) {
if (strcmp(entry.cat->name, "HJJJJJ")==0) {
}
if (mcount == ATTACH_BUFSIZ) {
prepareMethodLists(cls, mlists, mcount, NO, fromBundle);
rw->methods.attachLists(mlists, mcount);
mcount = 0;
}
mlists[ATTACH_BUFSIZ - ++mcount] = mlist;
fromBundle |= entry.hi->isBundle();
}
打印一下从分类里取出来的方法method_list_t *mlist = entry.cat->methodsForMeta(isMeta),元类取的是类方法,类取的是实例方法。\
我添加了2个实例方法,那么来看看isMeta为false,会发现从分类里取出的sayYes和sayNo方法, 而后会通过attachLists添加到rw的methods里。在之后打印rw的methods 看看
所以流程是map_images->_read_images->realizeClassWithoutSwift->methodizeClass->objc::unattachedCategories.attachToClass->attachCategories->rw->methods.attachLists
2. 非懒加载类,懒加载分类。
发现并没有走attachCategories,往前打断点,会发现methodizeClass方法里直接attachLists 到rw里了
// Install methods and properties that the class implements itself.
method_list_t *list = ro->baseMethods();
if (list) {
const char *tempChar;
tempChar = cls->nameForLogging();
if (strcmp(tempChar, "Person")==0) {
}
prepareMethodLists(cls, &list, 1, YES, isBundleClass(cls));
rw->methods.attachLists(&list, 1);
}
打印结果:
流程是map_images->_read_images->realizeClassWithoutSwift->methodizeClass->rw->methods.attachLists
3. 懒加载类,非懒加载分类。
既然是懒加载的类,那么只有在用到的时候才会加载了,map_images则不会断住了,通过attachCategories里的断点,看看堆栈信息。
可以看到是在load_images里加载的,在调用load方法之前会做一些处理,prepare_load_methods里会对非懒加载类和非懒加载分类进行处理。
流程是load_images->prepare_load_methods->realizeClassWithoutSwift->methodizeClass->objc::unattachedCategories.attachToClass->attachCategories->rw->methods.attachLists
4. 懒加载类,懒加载分类
这种情况需要第一个发送消息时才会加载,在main方法[Person new]一下,看看断点的堆栈信息。\
流程是第一次发送消息,调用objc_msgSend->lookUpImpOrForward->realizeClassWithoutSwift->methodizeClass->rw->methods.attachLists