流程分析
收到回调
_dyld_objc_notify_register(&map_images, load_images, unmap_image);
用到的数据结构:
struct loadable_class {
Class cls; // may be nil
IMP method;
};
// List of classes that need +load called (pending superclass +load)
// This list always has superclasses first because of the way it is constructed
static struct loadable_class *loadable_classes = nil;
static int loadable_classes_used = 0;
static int loadable_classes_allocated = 0;
- 当自定义类,没有实现load方法,而只有它的分类实现,那么不会加入到
_objc_catlist
数据段中 - 当自定义类和分类都实现了load方法,分类会加入到
_objc_catlist
数据段中
read_image
会将nlclslist
里的类进行realizeClassWithoutSwift
。这样如果一个自定义类,实现了load
方法,在镜像映射完成的时候,也就被填充了内部信息。(只是类,不是分类这一步)
load_image
会首先加载共享缓存中的分类
然后,准备那些实现了load
方法的类prepare_load_methods
void prepare_load_methods(const headerType *mhdr)
{
size_t count, i;
runtimeLock.assertLocked();
classref_t const *classlist =
_getObjc2NonlazyClassList(mhdr, &count);
for (i = 0; i < count; i++) {
schedule_class_load(remapClass(classlist[i]));
}
category_t * const *categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
for (i = 0; i < count; i++) {
category_t *cat = categorylist[i];
Class cls = remapClass(cat->cls);
if (!cls) continue; // category for ignored weak-linked class
if (cls->isSwiftStable()) {
_objc_fatal("Swift class extensions and categories on Swift "
"classes are not allowed to have +load methods");
}
printf("------------%s\n", cat->name);
realizeClassWithoutSwift(cls, nil);
ASSERT(cls->ISA()->isRealized());
add_category_to_loadable_list(cat);
}
}
这里有一个关键的方法是schedule_class_load
,它会先将父类的class的load
方法加入loadable_classes
static void schedule_class_load(Class cls)
{
if (!cls) return;
ASSERT(cls->isRealized()); // _read_images should realize
if (cls->data()->flags & RW_LOADED) return;
// Ensure superclass-first ordering
schedule_class_load(cls->getSuperclass());
add_class_to_loadable_list(cls);
cls->setInfo(RW_LOADED);
}
schedule_class_load
方法将有load
方法的类加入loadable_classes
category_t * const *categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
这个方法获取__objc_catlist2
数据段下的分类,通过add_category_to_loadable_list(cat);
方法加入loadable_categories
中
然后接下来通过call_load_methods()
方法调用+load
方法
void call_load_methods(void)
{
static bool loading = NO;
bool more_categories;
loadMethodLock.assertLocked();
// Re-entrant calls do nothing; the outermost call will finish the job.
if (loading) return;
loading = YES;
void *pool = objc_autoreleasePoolPush();
do {
// 1. Repeatedly call class +loads until there aren't any more
while (loadable_classes_used > 0) {
call_class_loads();
}
// 2. Call category +loads ONCE
more_categories = call_category_loads();
// 3. Run more +loads if there are classes OR more untried categories
} while (loadable_classes_used > 0 || more_categories);
objc_autoreleasePoolPop(pool);
loading = NO;
}
循环调用load方法,并调用分类的load方法
realizeClassWithoutSwift学习
realizeClassWithoutSwift
这方法很重要,有空看
/***********************************************************************
* realizeClassWithoutSwift
* Performs first-time initialization on class cls,
* including allocating its read-write data.
* Does not perform any Swift-side initialization.
* Returns the real class structure for the class.
* Locking: runtimeLock must be write-locked by the caller
**********************************************************************/